背景
近年来大数据BigData、人工智能AI、物联网Iot等行业发展迅猛,很多人都想要从事大数据技术开发工作,但是,请问要怎么做,路线是什么?从哪里开始学?学哪些?这是一个大问题。对于我自己来说,最近也在学一些大数据开发相关的技术,所以之前整理了一份《大数据技术学习路线》,希望对你有所帮助。
近年来大数据BigData、人工智能AI、物联网Iot等行业发展迅猛,很多人都想要从事大数据技术开发工作,但是,请问要怎么做,路线是什么?从哪里开始学?学哪些?这是一个大问题。对于我自己来说,最近也在学一些大数据开发相关的技术,所以之前整理了一份《大数据技术学习路线》,希望对你有所帮助。
聊两个问题,它们看似和推荐系统没有必然关系,但实际上,在你构建自己的推荐系统的时候,不可避免地会遇到这两个问题。
在推荐系统中,有一个刚需就是去重,那么说在哪些地方有去重的需求呢?
主要是在两个地方:一个是内容源去重,另一个是不重复给用户推荐。
聊两个问题,它们看似和推荐系统没有必然关系,但实际上,在你构建自己的推荐系统的时候,不可避免地会遇到这两个问题。
在推荐系统中,有一个刚需就是去重,那么说在哪些地方有去重的需求呢?
主要是在两个地方:一个是内容源去重,另一个是不重复给用户推荐。
数据库(DataBase,DB)是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。它是一个按数据结构来存储和管理数据的计算机软件系统。即数据库包含两层含义:保管数据的“仓库”以及数据管理的方法和技术。
数据库的特点包括:
表:在关系数据库中,数据库表是一系列二维数组的集合,用来存储数据和操作数据的逻辑结构。它由纵向的列和横向的行组成,行被称为记录,是组织数据的单位;列被称为字段,每一列表示记录的一个属性,都有相应的描述信息,如数据类型、数据宽度等。
数据类型:决定了数据在计算机中的存储格式,代表不同的信息类型。常用的数据类型有:整数数据类型,浮点数数据类型,精确小数类型,二进制数据类型,日期/时间数据类型,字符串数据类型。
主键(PRIMARY KEY)又称主码,用于唯一地标识表中得每一条记录。可以定义表中的一列或多列为主键,主键列上没有两行相同的值,也不能为空值。假如,下表给每一个作者分配一个“编号”,该编号作为表数据表的主键,如果出现相同的值,将提示错误,系统不能确定查询的究竟是哪一条记录;如果把作者的“姓名”作为主键,则不能出现重复的名字,这与现实不相符合,因此“姓名”字段不适合做为主键。
什么是开源:
PostgreSQL是一个开源数据库管理系统,那么什么是开源呢?开源是开放源码的简称,是被非赢利软件组织(美国的Open Source Initiative协会)注册为认证标记,并对其进行了正式的定义,用于描述那些源码可以被公众使用的软件,并且此软件的使用、修改和发行也不受许可证的限制。这意味着软件在提供的时候,同时提供了源码。开源许可赋予用户使用、修改和重新发布它而不需要付许可费用的权力。
数据库技术构成:
1.数据库系统有3个主要的组成部分。
⑴ 数据库:用于存储数据的地方。
⑵ 数据库管理系统:用于管理数据库的软件。
⑶ 数据库应用程序:为了提高数据库系统的处理能力所使用的管理
数据库的软件补充。
2.sql语言
对数据库进行查询和修改操作的语言叫做SQL。SQL的含义是结构化查询语言。SQL语言包含4个部分。
⑴ 数据定义语言(DDL):DROP、CREATE、ALTER等语句。
⑵ 数据操作语言(DML):INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。
⑶ 数据查询语言(DQL):SELECT语句。
⑷ 数据控制语言(DCL):GRANT、REVOKE、COMMIT、ROLLBACK等语句。
3.数据库访问技术
1.客户机-服务器软件
服务器是整个应用系统资源的存储与管理中心,多个客户端则各自处理相应的功能,共同实现完整的应用。在客户/服务器结构中,客户端用户的请求被传送到数据库服务器,数据库服务器进行处理后,将结果返回给用户,从而减少了网络数据传输量。
用户使用应用程序时,首先启动客户端通过有关命令告知服务器进行连接以完成各种操作,而服务器则按照此请示提供相应的服务。每一个客户端软件的实例都可以向一个服务器或应用程序服务器发出请求。
2.PostgreSQL发展历程
PostgreSQL的发展历程可以追溯到1986年,加州大学伯克利分校开发一个名叫Postgres的关系数据库服务器。
到了1994年,向Postgres 中增加了SQL语言的解释器,命名为Postgres95,并随后将其源代码发布到互联网上供大家使用,成为一个开放源码的数据库管理系统。
到了1996年,Postgres95名称被更改为PostgreSQL,表示它支持查询语言标准,同时版本号也重新从6.0开始。自从版本6.0之后,出现了很多后续发行,在系统中也出现了很多改进。
2016年9月29日,PostgreSQL全球开发组发布PostgreSQL 9.6版本,该版本允许用户纵向扩展和横向扩展来提高数据库的查询性能,同时增加了并行查询、同步复制改进、短语搜索等功能,从而使复制、聚合、索引、排序等过程变得更加高效,使其性能和可用性得到极大提高。
2018年10月18日,PostgreSQL全球开发组发布PostgreSQL 11版本。
3.PostgreSQL的优势
⑴ 价格
⑵ 速度
⑶ 容易使用
⑷ 可移植性
⑸ 丰富的接口
⑹ 支持查询语言
⑺ 相互配合的开源软件较多
⑻ 安全性和连接性
爬取百度图片并把图片存到本地:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115import re
import requests
from urllib import error
from bs4 import BeautifulSoup
import os
num = 0
numPicture = 0
file = ''
List = []
def Find(url):
global List
print('正在检测图片总数,请稍等.....')
t = 0
i = 1
s = 0
while t < 1000:
Url = url + str(t)
try:
Result = requests.get(Url, timeout=7)
except BaseException:
t = t + 60
continue
else:
result = Result.text
pic_url = re.findall('"objURL":"(.*?)",', result, re.S) # 先利用正则表达式找到图片url
s += len(pic_url)
if len(pic_url) == 0:
break
else:
List.append(pic_url)
t = t + 60
return s
def recommend(url):
Re = []
try:
html = requests.get(url)
except error.HTTPError as e:
return
else:
html.encoding = 'utf-8'
bsObj = BeautifulSoup(html.text, 'html.parser')
div = bsObj.find('div', id='topRS')
if div is not None:
listA = div.findAll('a')
for i in listA:
if i is not None:
Re.append(i.get_text())
return Re
def dowmloadPicture(html, keyword):
global num
# t =0
pic_url = re.findall('"objURL":"(.*?)",', html, re.S) # 先利用正则表达式找到图片url
print('找到关键词:' + keyword + '的图片,即将开始下载图片...')
for each in pic_url:
print('正在下载第' + str(num + 1) + '张图片,图片地址:' + str(each))
try:
if each is not None:
pic = requests.get(each, timeout=7)
else:
continue
except BaseException:
print('错误,当前图片无法下载')
continue
else:
string = file + r'\\' + keyword + '_' + str(num) + '.jpg'
fp = open(string, 'wb')
fp.write(pic.content)
fp.close()
num += 1
if num >= numPicture:
return
if __name__ == '__main__': # 主函数入口
word = input("请输入搜索关键词(可以是人名,地名等): ")
# 比如百度图片上搜索:苹果
# add = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=%e8%8b%b9%e6%9e%9c&pn=120'
url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + word + '&pn='
tot = Find(url)
Recommend = recommend(url) # 记录相关推荐
print('经过检测{}类图片共有{}张'.format(word, tot))
numPicture = int(input('请输入想要下载的图片数量: '))
file = input('请建立一个存储图片的文件夹,输入文件夹名称即可:')
y = os.path.exists(file)
if y == 1:
print('该文件已存在,请重新输入')
file = input('请建立一个存储图片的文件夹,)输入文件夹名称即可')
os.mkdir(file)
else:
os.mkdir(file)
t = 0
tmp = url
while t < numPicture:
try:
url = tmp + str(t)
result = requests.get(url, timeout=10)
print(url)
except error.HTTPError as e:
print('网络错误,请调整网络后重试')
t = t + 60
else:
dowmloadPicture(result.text, word)
t = t + 60
print('当前搜索结束,感谢使用')
print('猜你喜欢')
for re in Recommend:
print(re, end=' ')
执行结果如下,比如搜索杨树:
存到本地的效果如下图:
共勉,(๑•̀ㅂ•́)و✧加油
这是一个绕口令,要一口气说完。开始做绕口令练习的时候,中间可以换一换气,练到气息有了控制能力的时候,逐渐把换气次数减少,最后争取一口气说完,甚至多说几个枣儿。必须进行共鸣训练。 以下介绍几种简单易行的共训练方法。 方法/步骤 1, 放松喉头,用“哼哼”音唱歌。 2,学鸭叫声。挺软腭,口腔张开成一圆筒,边发gaga音,边仔细体会,共鸣运用得好的gaga音好听,共鸣运用得不好的gaga音枯燥、刺耳。 3, 学牛叫声。类似打电话的“嗯”(什么?)和“嗯”(明白了)。 4, 牙关大开合,同时发出“啊”音。 5, 模拟汽笛长鸣声。(di)既可平行发音,也可由大到小或由小到大地变化发音。 6, 做扩胸运动,同时尽量发高亢或尽量低沉的声音。 7, “气泡音”练习。闭嘴,用轻匀的气流冲击声带,使之发出细小的抖动声。 8,音阶层练习。选一句话,在本人音域范围内,先用低调说,一级一级地升高,然后又一级一级地下降,在一句高一句低,高低交替,一句话又高到低,再由低到高。 9,夸张四声练习。选择韵母因素较多的词语或成语,运用共鸣技巧做夸张四声的训练。如:清——正——廉——洁——,英——勇——顽——强——。 10, 大声呼唤练习。假设某人在离自己100米处,大声呼唤:张——师——傅——,快——回——来——!喂——,那——里——危——险——,快——离——开——! 字的对比练习。训练要求是,对比平翘舌声母,再分别组词作朗诵练习。 > 平——翘 滋——之 字——只咋——扎 总——中 > 嘴——追 增——正 尊——准 藏——张 > 词的对比练习。训练要求是:对比平翘舌声母,再分别用每个词说句话。 > 平——翘 自主——支柱栽花——摘花 木材——木柴 > 推辞——推迟 私人——诗人 司机——实际 > 组词练习。训练要求是:用平翘舌音组词,辨音记词,再用每个词说句话。 > Z——zh 在职 杂志 栽种 增长 自重 宗旨 > Zh——z 渣滓 张嘴 种族 长子 沼泽 振作 > C——ch 财产 草场 猜出 采茶 彩绸 餐车 > Ch——c 车次场次 蠢才 纯粹 差错 陈词 > Sh——s 三十 丧生 扫射 私塾 四十 四声 > S——sh 哨所 山色 深思 神速 上诉 深邃 绕口令-1 八百标兵(b、p) 八百标兵奔北坡,炮兵并排北边跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。 炮兵和步兵(b、p、m)炮兵攻打八面坡,炮兵排排炮弹齐发射。步兵逼近八面坡,歼敌八千八百八十多。 绕口令-2 一平盆面(b、p) 一平盆面,烙一平盆饼,饼碰盆,盆碰饼。 巴老爷芭蕉树(b、p)巴老爷有八十八棵芭蕉树来了八十八个把式要在巴老爷八十八棵芭蕉树下住。巴老爷拔了八十八棵芭蕉树,不让八十八个把式在八十八棵芭蕉树下住,八十八个把式烧了八十八棵芭蕉树,巴老爷在八十八棵树边哭。 绕口令-8 哥挎瓜筐过宽沟(g、k) 哥挎瓜筐过宽沟,赶快过沟看怪狗,光看怪狗瓜筐扣,瓜滚筐空哥怪狗。 哥哥捉鸽(g、k、h) 哥哥过河捉个鸽,回家割鸽来请客,客人吃鸽称鸽肉,哥哥请客乐呵呵。 老爷堂上一面鼓(g、k、h)老爷堂上一面鼓,鼓上一只皮老虎,皮老虎抓破了鼓,就拿块破布往上补,只见过破布补破裤,哪见过破布补破鼓。 知自在自然自在;
悟如来想如来,
非如来如是如来。
长扁担,短扁担长扁担,短扁担,
长扁担比短扁担长半扁担;
短扁担比长扁担短半扁担。
长扁担绑在短板凳上,
长板凳不能绑在比短扁担长半扁担的长扁担上;
短板凳也不能绑在比长扁担短半扁担的短扁担上。
民兵排选标兵
民兵排选标兵,
六班的标兵、七班的标兵、八班的标兵,
评比台前比选先进,
比比谁更先进,
选拔八名全排标兵上北京。
盆和棚天上一个盆,
地下一个棚,
盆碰棚,棚碰盆,
棚倒了,盆碎了,
是棚赔盆,
还是盆赔棚?
他们要学理发。
理化不是理发,
理发不是理化。
学会理化不会理发,
学会理发也不懂理化。
量窗量床又量墙量窗量床又量墙,
跳上床量窗,
靠住墙量床,
墙比张床长,
床又比窗长,
窗长不过床,
床又长不过墙,
所以墙比床比窗长,
读不顺就去撞墙。
钉上挂条绳,
滑落绳下瓶,
打碎瓶下灯,
砸破灯下盆。
瓶打灯,灯打盆,
盆骂灯,灯骂瓶,
瓶骂绳,绳骂钉,
钉怪绳,绳怪瓶,
瓶怪灯,灯怪盆,
叮叮当当当当叮,
乒乒乓乓乓乓乒。
爹打弟,弟滚地爹打弟,弟滚地,
嫂嫂烧苕哄地弟;
姐呼鸡,鸡藏箕,
叔叔竖黍惊箕鸡。
奋发商店卖混纺奋发商店卖混纺,
有红混纺,黄混纺,粉红混纺,花混纺,
纷繁的混纺让大娘着了慌。
仿佛进了混纺的大世界,
眼也花,手也忙。
吩咐女儿快快挑混纺。
理化和理发我们要学理化,
他们要学理发。
理化不是理发,
理发不是理化。
学会理化不会理发,
学会理发也不懂理化。
从北边来了一个阿巴阿巴,背上背着一个伸缩喇叭。
南边提着比目鱼的啦的高高大大的喇嘛,要拿比目鱼的啦换北边背伸缩喇叭的阿巴阿巴的伸缩喇叭。
阿巴阿巴不愿拿伸缩喇叭换高高大大的喇嘛的比目鱼的啦。
高高大大的喇嘛非要换背伸缩喇叭阿巴阿巴的伸缩喇叭。
高高大大的喇嘛抡起比目鱼的啦抽了背伸缩喇叭阿巴阿巴一比目鱼的啦,阿巴阿巴摘下伸缩喇叭打了提比目鱼的啦的高高大大的喇嘛一伸缩喇叭。也不知是提着比目鱼的啦的高高大大的喇嘛抽了背伸缩喇叭的阿巴阿巴一比目鱼的啦,还是背伸缩喇叭的阿巴阿巴打了提比目鱼的啦的高高大大的喇嘛一伸缩喇叭。
高高大大的喇叭回家炖比目鱼的啦。
阿巴阿巴滴滴答答吹伸缩喇叭。
小鸡鸡不尿尿各有各的道天有天道地有地道
小鸡鸡不尿尿各有各的道
听说你会剑道忍道人道学过柔道抬拳道还会空手道和李小龙学过截拳道
小服呀说你爹不走正道你妈就走歪道你还不进孝道整天横行霸道还胡说八道脚踏黑白两道出门警车开道你快去你吗了个一群二白3拳4轴无炎六色七上八下五花八门三长两短千变万化五万十色万紫千红里的大比里组织一下语言深空进化一下你的长相吗的~!~气死我了小服呀你在跟我装我就一个大拳头给你打到西伯力亚叫你抱着北极熊叫爸
二哥有小锅,
大哥要换二哥的小锅,
二哥不换大哥的大锅。
班干部管班干部班干部管班干部(重复五遍)
树顶一只猴树顶一只猴,
树脚一只狗;
猴狗跋落来撞着狗,
狗吠猴哮,猴走狗也走,
不知是猴怕狗,还是狗怕猴。
2,八百标兵奔北坡,
炮兵并排北边跑,
炮兵怕把标兵碰,
标兵怕碰炮兵炮。
3,断头台倒吊短单刀,
歹徒登台偷单刀,
断头台塌盗跌倒,
对对单刀叮当掉。
八百标兵奔北坡,
炮兵并排北边跑。
炮兵怕把标兵碰,
标兵怕碰炮兵炮。
寡妇马华莎,
光汉贾家嘉。
马华莎脸上麻,
贾家嘉独眼瞎,
两人登记成了家。
贾家嘉不嫌马华莎麻,
马华莎不嫌贾家嘉瞎.
伯伯簸谷子,
簸去谷秕子。
婆婆簸谷子,
簸去秕谷子。
伯伯和婆婆,
簸谷作种子。
阿拉屋里有只白脚白鼻头白尾巴花白猫,
隔壁大伯伯啦也有只白脚白鼻头白尾巴花白猫。
阿拉个只白脚白鼻头白尾巴花白猫,
去咬杀了隔壁大伯伯啦个只白脚白鼻头白尾巴花白猫。
阿拉个只白脚白鼻头白尾巴花白猫,
去赔给了大伯伯啦个只白脚白鼻头白尾巴花白猫,
阿拉个只白脚白鼻头白尾巴花白猫白里格白养了—遭。
八百标兵奔北坡,
炮兵并排北边跑,
炮兵怕把标兵碰,
标兵怕碰炮兵炮.
哥哥弟弟坡前坐,
坡上卧着一只鹅,
坡下流着一条河,
哥哥说:宽宽的河,
弟弟说:白白的鹅.
鹅要过河,
河要渡鹅.
不知是鹅过河,
还是河渡鹅.
嘴说腿,腿说嘴,
嘴说腿爱跑腿,
腿说嘴爱卖嘴.
光动嘴不动腿,
光动腿不动嘴,
不如不长腿和嘴.
八百标兵奔北坡,
炮兵并排北边跑。
炮兵怕把标兵碰,
标兵怕碰炮兵炮。
寡妇马华莎,
光汉贾家嘉。
马华莎脸上麻,
贾家嘉独眼瞎,
两人登记成了家。
贾家嘉不嫌马华莎麻,
马华莎不嫌贾家嘉瞎.
伯伯簸谷子,
簸去谷秕子。
婆婆簸谷子,
簸去秕谷子。
伯伯和婆婆,
簸谷作种子。
哥哥挎筐过宽沟,
快过宽沟看怪狗,
光看怪狗瓜筐扣,
瓜滚筐扣哥怪狗.
八百标兵奔北坡,
炮兵并排北边跑,
炮兵怕把标兵碰,
标兵怕碰炮兵炮.
哥哥弟弟坡前坐,
坡上卧着一只鹅,
坡下流着一条河,
哥哥说:宽宽的河,
弟弟说:白白的鹅.
鹅要过河,
河要渡鹅.
不知是鹅过河,
还是河渡鹅.
嘴说腿,腿说嘴,
嘴说腿爱跑腿,
腿说嘴爱卖嘴.
光动嘴不动腿,
光动腿不动嘴,
不如不长腿和嘴.
哥哥弟弟坡前坐,
坡上卧着一只鹅,
坡下流着一条河,
哥哥说:宽宽的河,
弟弟说:白白的鹅.
鹅要过河,
河要渡鹅.
不知是鹅过河,
还是河渡鹅.
嘴说腿,腿说嘴,
嘴说腿爱跑腿,
腿说嘴爱卖嘴.
光动嘴不动腿,
光动腿不动嘴,
不如不长腿和嘴.
夹着火车上皮包.
回头一看人咬狗.
拿起狗来打石头,
又怕石头咬着手.
断头台倒吊短单刀,
歹徒登台偷单刀,
断头台塌盗跌倒,
对对单刀叮当掉.
有个小孩叫小杜,
上街打醋又买布.
买了布,打了醋,
回头看见鹰抓兔.
放下布,搁下醋,
上前去追鹰和兔,
飞了鹰,跑了兔.
洒了醋,湿了布.
八百标兵奔北坡,
炮兵并排北边跑。
炮兵怕把标兵碰,
标兵怕碰炮兵炮。
寡妇马华莎,
光汉贾家嘉。
马华莎脸上麻,
贾家嘉独眼瞎,
两人登记成了家。
贾家嘉不嫌马华莎麻,
马华莎不嫌贾家嘉瞎.
伯伯簸谷子,
簸去谷秕子。
婆婆簸谷子,
簸去秕谷子。
伯伯和婆婆,
簸谷作种子。
阿拉屋里有只白脚白鼻头白尾巴花白猫,
隔壁大伯伯啦也有只白脚白鼻头白尾巴花白猫。
阿拉个只白脚白鼻头白尾巴花白猫,
去咬杀了隔壁大伯伯啦个只白脚白鼻头白尾巴花白猫。
阿拉个只白脚白鼻头白尾巴花白猫,
去赔给了大伯伯啦个只白脚白鼻头白尾巴花白猫,
阿拉个只白脚白鼻头白尾巴花白猫白里格白养了—遭。
八百标兵奔北坡,
炮兵并排北边跑。
炮兵怕把标兵碰,
标兵怕碰炮兵炮。
哥哥挎筐过宽沟哥哥挎筐过宽沟,
快过宽沟看怪狗。
光看怪狗瓜筐扣,
瓜滚筐扣哥怪狗。
洞庭山上有根藤
洞庭山上有根藤,
藤上系着小铜铃。
风吹藤动铜铃动,
风停藤静铜铃停。
九与酒
九月九,九个酒迷喝醉酒。
九个酒杯九杯酒,九个酒迷喝九口。
喝罢九口酒,又倒九杯酒。
九个酒迷端起酒,“咕咚、咕咚”又九口。
九杯酒,酒九口,喝罢九个酒迷醉了酒。
天上一颗星
天上一颗星,地下一块冰, 屋上一只鹰,墙上一排钉。
抬头不见天上的星,乒乓乒乓踏碎地下的冰,
啊嘘啊嘘赶走了屋上的鹰,唏哩唏哩拔掉了墙上的钉。
九与酒
九月九,九个酒迷喝醉酒。
九个酒杯九杯酒,九个酒迷喝九口。
喝罢九口酒,又倒九杯酒。
九个酒迷端起酒,“咕咚、咕咚”又九口。
九杯酒,酒九口,喝罢九个酒迷醉了酒。
南边来了他大大伯子家的大搭拉尾巴耳朵狗,
北边来了他二大伯子家的二搭拉尾巴耳朵狗.
他大大伯家的大搭拉尾巴耳朵狗,咬了他二大伯家的二搭拉尾巴耳朵狗一口;
他二大伯家的二搭拉尾巴耳朵狗,也咬了他大大伯家的大搭拉尾巴耳朵狗一口.
不知是他大大伯家的大搭拉尾巴耳朵狗,先咬了他二大伯家的二搭拉尾巴耳朵狗;
还是他二大伯家的二搭拉尾巴耳朵狗,先咬了他大大伯家的大搭拉尾巴耳朵狗.
喇嘛与哑巴
打南边来了个哑巴,腰里别了个喇叭;
打北边来了个喇嘛,手里提了个獭犸.
提着獭犸的喇嘛要拿獭犸换别着喇叭的哑巴的喇叭;
别着喇叭的哑巴不愿拿喇叭换提着獭犸的喇嘛的獭犸.
不知是别着喇叭的哑巴打了提着獭犸的喇嘛一喇叭;
还是提着獭犸的喇嘛打了别着喇叭的哑巴一獭犸.
喇嘛回家炖獭犸;
哑巴嘀嘀哒哒吹喇叭
凤凰台上落凤凰。
红凤凰,蓝凤凰,
粉红凤凰黄凤凰。
凤凰落在凤凰台,
凤凰山上凤花香。
凤凰山上放凤凰凤凰山上放凤凰,
凤凰山下凤凰唱。
碰见凤凰数凤凰,
粉红凤同黄凤凰。
红凤凰绿凤凰黄凤凰红凤凰,
绿凤凰,
粉红凤凰黄凤凰。
凤凰飞,飞凤凰,
凤凰山里出凤凰。
小妞妞赶集小妞妞,去赶集,
集上有人卖鸭梨;卖的那梨真叫甜,
集上有人在卖镰;卖的那镰真叫快,
集上有人在卖菜;卖的那菜真叫鲜,
集上有人在卖烤烟;卖的那烟真叫好,
集上有人在卖红枣;卖的那枣真叫红,
集上有人卖大绳;卖的那绳真叫长,
集上有人卖香糖;卖的那糖真叫香,
集上有人卖鲜姜;卖的那姜真叫辣,
集上有人卖年画;卖的那画真好看,
集上有人卖大蒜;卖的大蒜个个大,
集上有人卖红蜡;卖的那蜡真叫粗;
集上有人卖小猪;小花猪,
猛一叫,吓了妞妞一大跳。
凤凰台上落凤凰。
红凤凰,蓝凤凰,
粉红凤凰黄凤凰。
凤凰落在凤凰台,
凤凰山上凤花香。
凤凰山上放凤凰凤凰山上放凤凰,
凤凰山下凤凰唱。
碰见凤凰数凤凰,
粉红凤同黄凤凰。
红凤凰绿凤凰黄凤凰红凤凰,
绿凤凰,
粉红凤凰黄凤凰。
凤凰飞,飞凤凰,
凤凰山里出凤凰。
小妞妞赶集小妞妞,去赶集,
集上有人卖鸭梨;卖的那梨真叫甜,
集上有人在卖镰;卖的那镰真叫快,
集上有人在卖菜;卖的那菜真叫鲜,
集上有人在卖烤烟;卖的那烟真叫好,
集上有人在卖红枣;卖的那枣真叫红,
集上有人卖大绳;卖的那绳真叫长,
集上有人卖香糖;卖的那糖真叫香,
集上有人卖鲜姜;卖的那姜真叫辣,
集上有人卖年画;卖的那画真好看,
集上有人卖大蒜;卖的大蒜个个大,
集上有人卖红蜡;卖的那蜡真叫粗;
集上有人卖小猪;小花猪,
猛一叫,吓了妞妞一大跳。
李力丽黎礼立夫妻去赶集李力丽,黎礼立,
夫妻双双去赶集,
李力丽的丈夫黎礼立,
赶集去卖竹蔑席,
黎礼立的妻子李力丽,
赶集去卖肥母鸡.
黎礼立卖了竹蔑席买只电视机,
李力丽卖了肥母鸡买件呢子衣.
红凤凰绿凤凰黄凤凰
红凤凰,
绿凤凰,
粉红凤凰黄凤凰。
凤凰飞,飞凤凰,
凤凰山里出凤凰。小妞妞赶集
小妞妞,去赶集,
集上有人卖鸭梨;卖的那梨真叫甜,
集上有人在卖镰;卖的那镰真叫快,
集上有人在卖菜;卖的那菜真叫鲜,
集上有人在卖烤烟;卖的那烟真叫好,
集上有人在卖红枣;卖的那枣真叫红,
集上有人卖大绳;卖的那绳真叫长,
集上有人卖香糖;卖的那糖真叫香,
集上有人卖鲜姜;卖的那姜真叫辣,
集上有人卖年画;卖的那画真好看,
集上有人卖大蒜;卖的大蒜个个大,
集上有人卖红蜡;卖的那蜡真叫粗;
集上有人卖小猪;小花猪,
猛一叫,吓了妞妞一大跳。李力丽黎礼立夫妻去赶集
李力丽,黎礼立,
夫妻双双去赶集,
李力丽的丈夫黎礼立,
赶集去卖竹蔑席,
黎礼立的妻子李力丽,
赶集去卖肥母鸡.
黎礼立卖了竹蔑席买只电视机,
李力丽卖了肥母鸡买件呢子衣.
小齐、小吉和小余跟着小鞠去赶集
小齐、小吉和小余,
跟着小鞠去赶集,
路上遇见一头小毛驴,
在嘁哩喀喳啃树皮。
小齐和小吉,
小余和小鞠,
一齐跑过去,
小齐和小吉把小毛驴送到村西饲养棚里面去。高个子矮个子穿高跟鞋
高个子穿的半高跟,矮个子穿的高高跟。
高个子不穿高高跟,比矮个子穿高高跟高半高跟,
矮个子穿上高高跟,比高个子穿半高跟还矮半高跟。
绣个金凤凰放金光,
绣个银凤凰放银光,
绣个粉红凤凰放粉红光,
绣个红凤凰放红光,
绣个黄凤凰放黄光,
凤凰姊,绣凤凰,
绣的凤凰会放光。
芳芳贴凤凰春天里,杏花黄,
奶奶给我剪凤凰。
我和妹妹手挽手,
一起来把歌儿唱:
一进门,粉白墙,
刚刚芳芳贴凤凰,
红凤凰,蓝凤凰,
粉红凤凰黄凤凰。
凤凰台上落凤凰。
红凤凰,蓝凤凰,
粉红凤凰黄凤凰。
凤凰落在凤凰台,
凤凰山上凤花香。
凤凰山上放凤凰凤凰山上放凤凰,
凤凰山下凤凰唱。
碰见凤凰数凤凰,
粉红凤同黄凤凰。
红凤凰绿凤凰黄凤凰红凤凰,
绿凤凰,
粉红凤凰黄凤凰。
凤凰飞,飞凤凰,
凤凰山里出凤凰。
四和十十和四十四和四十四十和十四说好四和十得靠舌头和牙齿谁说四十是细席他
的舌头没用力谁说十四是适时他的舌头4.没伸直认真学常练习十四、四十、四十四3.牛和柳
河边一棵柳,柳下一头牛,牛要去顶柳,柳条缠牛头。4.松和钟
丛岭种青松,青松挂铜钟,
风行松动铜铃鸣,风停松静钟声停。5.帆船
帆船翻,翻帆船,竖起桅杆撑开帆。
风吹帆,,帆引船,帆船顺风转海湾。6.打铁
张打铁,李打铁,打把刀,送姐姐。
姐姐留我歇,我不歇,我在张家学打铁。7.实事求是
知道就是知道,不知道就是不知道。不要知道说不知道,也不要不知道说知道。
实事求是一定要做到,这才是不折不扣的真知道。8.牛皮好绷鼓
手里起泡泡,泡里出青草,
青草好饲草,牛皮好绷鼓,
绷来鼓,急鼓鼓,十八夜里敲铜鼓。9.河里有只船
河里有只船船上挂白帆风吹帆张船向前无风帆落停下船10.兜装豆
兜里装豆,豆装满兜,兜破漏豆。倒出豆,补破兜,补好兜,又装豆,装满兜,不漏豆。11.颠倒歌
咬牛奶,喝面包,夹着火车上皮包。东西街,南北走,出门看见人咬狗。拿起狗来打砖头,又怕砖头咬我手。
哥哥挎筐过宽沟,
快过宽沟看怪狗,
光看怪狗瓜筐扣,
瓜滚筐扣哥怪狗.
八百标兵奔北坡,
炮兵并排北边跑,
炮兵怕把标兵碰,
标兵怕碰炮兵炮.
哥哥弟弟坡前坐,
坡上卧着一只鹅,
坡下流着一条河,
哥哥说:宽宽的河,
弟弟说:白白的鹅.
鹅要过河,
河要渡鹅.
不知是鹅过河,
还是河渡鹅.
打枣
出东门,
过大桥,
大桥底下一树枣。
拿着竿子去打枣,
青的多,
红的少:
一个枣、两个枣、三个枣、四个枣、五个枣、六个枣、七个枣、八个枣、九个枣、十个枣;
十个枣、九个枣、八个枣、七个枣、六个枣、五个枣、四个枣、三个枣、两个枣、一个枣。
一个半罐是半罐,两个半罐是一罐;三个半罐是一罐半,四个半罐是两罐;五个半罐是两罐半,
六个半罐是三满罐;七个、八个、九个半罐,请你算算是多少罐。
给山下三小子借了三斗三升酸枣子。过年山下三小子打下酸枣子,
四和十 四和十,十和四,十四和四十, 四十和十四。 说好四和十得靠舌头和牙齿, 谁说四十是细席, 他的舌头没用力;谁说十四是适时, 他的舌头没伸直。认真学,常练习, 十四、四十、四十四。
河里有只船,
船上挂白帆,
风吹帆张船向前,
无风帆落停下船。种南瓜
东门童家门东董家,童、董两家,同种冬瓜,童家知道董家冬瓜大,来到董家学种冬瓜。门东董家懂种冬瓜,来教东门童家种冬瓜。童家、董家都懂得种冬瓜,童、董两家的冬瓜比桶大。酒换油
一葫芦酒九两六,一葫芦油六两九。六两九的油,要换九两六的酒,九两六的酒,不换六两九的油。九个酒迷喝醉酒
九月九,九个酒迷喝醉酒。九个酒杯九杯酒,九个酒迷喝九口。喝罢九口酒,又倒九杯酒。九个酒迷端起酒,咕咚、咕咚又九口。九杯酒,酒九口,喝罢九个酒迷醉了酒。
打枣
出东门,
过大桥,
大桥底下一树枣。
拿着竿子去打枣,
青的多,
红的少:
一个枣、两个枣、三个枣、四个枣、五个枣、六个枣、七个枣、八个枣、九个枣、十个枣;
十个枣、九个枣、八个枣、七个枣、六个枣、五个枣、四个枣、三个枣、两个枣、一个枣。
一个半罐是半罐,两个半罐是一罐;三个半罐是一罐半,四个半罐是两罐;五个半罐是两罐半,
六个半罐是三满罐;七个、八个、九个半罐,请你算算是多少罐。
给山下三小子借了三斗三升酸枣子。过年山下三小子打下酸枣子,
鹅过河 哥哥弟弟坡前坐, 坡上卧着一只鹅, 坡下流着一条河, 哥哥说:宽宽的河, 弟弟说:白白的鹅。 鹅要过河, 河要渡鹅。 不知是鹅过河, 还是河渡鹅。 颠倒歌 咬牛奶,喝面包, 夹着火车上皮包。 东西街,南北走, 出门看见人咬狗。 拿起狗来打砖头, 又怕砖头咬我手。
小凤提着圆灯笼,
小龙提着方灯笼。
小凤的圆灯笼上画着龙,
小龙的方灯笼上画着凤,
小凤要拿圆龙灯笼换小龙的方凤灯笼。
大花碗里扣个大花活蛤蟆。
南边来了他大大伯子家的大搭拉尾巴耳朵狗,
北边来了他二大伯子家的二搭拉尾巴耳朵狗。
他大大伯家的大搭拉尾巴耳朵狗,咬了他二大伯家的二搭拉尾巴耳朵狗一口;
他二大伯家的二搭拉尾巴耳朵狗,也咬了他大大伯家的大搭拉尾巴耳朵狗一口。
不知是他大大伯家的大搭拉尾巴耳朵狗,先咬了他二大伯家的二搭拉尾巴耳朵狗;
还是他二大伯家的二搭拉尾巴耳朵狗,先咬了他大大伯家的大搭拉尾巴耳朵狗。
扁但是扁的,
板凳是板的。
扁担不是板凳,
板凳不是扁担。
别把扁担说成板凳,
别把板凳说成扁担。
一很长扁担,
一根短扁担,
长扁担比短扁担长半扁担,
短扁担比长扁担短半扁担。
路上走着个扛短扁担的,
对面来了个搬短板凳的。
是扛短扁担的打搬短板凳的,
还是搬短板凳的打扛短扁担的?
扁但是扁的,
板凳有板的。
扁担扁,
扁的不都是扁担,
板凳板,
有板的不都是板凳
扁担不是板凳,
板凳不是扁担,
别把扁担说成板凳
别把板凳说成扁担
扁但是扁的,
板凳是板的。
扁担不是板凳,
板凳不是扁担。
别把扁担说成板凳,
别把板凳说成扁担。
一很长扁担,
一根短扁担,
长扁担比短扁担长半扁担,
短扁担比长扁担短半扁担。
路上走着个扛短扁担的,
对面来了个搬短板凳的。
是扛短扁担的打搬短板凳的,
还是搬短板凳的打扛短扁担的?
板凳是板的。
扁担不是板凳,
板凳不是扁担。
别把扁担说成板凳,
别把板凳说成扁担。
扁担和板凳打架路上走着个扛短扁担的,
对面来了个搬短板凳的。
是扛短扁担的打搬短板凳的,
还是搬短板凳的打扛短扁担的?
扁担不是板凳扁担是扁的,
板凳有板的。
扁担扁,
扁的不都是扁担,
板凳板,
有板的不都是板凳。
扁担不是板凳,
板凳不是扁担,
别把扁担说成板凳,
别把板凳说成扁担。
板凳是板的。
扁担不是板凳,
板凳不是扁担。
别把扁担说成板凳,
别把板凳说成扁担。
扁担和板凳打架路上走着个扛短扁担的,
对面来了个搬短板凳的。
是扛短扁担的打搬短板凳的,
还是搬短板凳的打扛短扁担的?
扁担不是板凳扁担是扁的,
板凳有板的。
扁担扁,
扁的不都是扁担,
板凳板,
有板的不都是板凳。
扁担不是板凳,
板凳不是扁担,
别把扁担说成板凳,
别把板凳说成扁担。
八斤鸡和八斤狗
我家有个肥净白净八斤鸡,飞到张家后院里。
张家院有个肥净白净八斤狗,咬了我的肥净白净八斤鸡。
我拿他的肥净白净八斤狗赔了我的肥净白净八斤鸡。
一条裤子七道缝儿
一条裤子七道缝,斜缝竖缝和横缝,缝了斜缝缝竖缝,缝了竖缝缝斜缝
画凤凰
粉红墙上画凤凰 凤凰画在粉红墙 红凤凰、粉凤凰 红粉凤凰花凤凰
三山撑四水,四水绕三山,三山四水春常在,四水三山四时春(《三山撑四水》)。
司机买雌鸡,仔细看雌鸡,四只小雌鸡,叽叽好欢喜,司机笑嘻嘻(《司机买雌鸡》)。
大车拉小车,小车拉小石头,石头掉下来,砸了小脚指头(《大车拉小车》)。
夏日无日日亦热,冬日有日日亦寒,春日日出天渐暖,晒衣晒被晒褥单,秋日天高复云淡,遥看红日迫西山(《说日》)。
四声:石室诗士施史,嗜狮,誓食十狮,氏时时适市,氏视十狮,恃矢势,使是十狮逝世,氏拾是十狮尸,适石室,石室湿,氏使侍拭石室,石室拭,氏始试食十狮尸,食时,始识十狮尸实是十石狮尸,试释是事实(《施氏食狮史》)。
七巷一个漆匠,西巷一个锡匠,七巷漆匠偷了西巷锡匠的锡,西巷锡匠偷了七巷漆匠的漆。(《漆匠和锡匠》)。
哥挎瓜筐过宽沟,赶快过沟看怪狗。光看怪狗瓜筐扣,瓜滚筐空哥怪狗(《哥挎瓜筐过宽沟》)。
一堆粪,一堆灰,灰混粪,粪混灰(《一堆粪》)。
画狮子 有个好孩子,拿张图画纸, 来到石院子,学画石狮子。 一天来画一次石狮子, 十天来画十次石狮子。 次次画石狮子,天天画石狮子, 死狮子画成了活狮子。
羊 和 狼 东边来了一只小山羊, 西边来了一只大灰狼, 一起走到小桥上, 小山羊不让大灰狼, 大灰狼不让小山羊, 小山羊叫大灰狼让小山羊, 大灰狼叫小山羊让大灰狼, 羊不让狼,狼不让羊, 扑通一起掉到河中央。
鸟 和 猫 树上一只鸟, 地上一只猫。 地上的猫想咬树上的鸟, 树上的鸟想啄猫的毛。 黄狗咬我手 清早上街走,走到周家大门口, 门里跳出一只大黄狗, 朝我哇啦哇啦吼。 我拾起石头打黄狗, 黄狗跳上来就咬我的手。 也不知我手里的石头 打没打着周家的大黄狗, 周家的大黄狗咬没咬着我的手?
小 花 猫 小花猫爱画画,先画一朵腊梅花, 又画一个小喇叭,带着腊梅花, 吹着小喇叭,回家去见妈妈, 妈妈见了笑哈哈。
毛毛和猫猫 毛毛有一顶红帽,猫猫有一身灰毛。 毛毛要猫猫的灰毛, 猫猫要毛毛的红帽。 毛毛把红帽交给猫猫, 猫猫给毛毛几根灰毛。
小鱼大雁 小鱼入鱼网鱼网捕鱼鱼难逃, 大雁过雁塔雁塔留雁雁不留。
捉 兔 一位爷爷他姓顾,上街打醋又买布。 买了布,打了醋,回头看见鹰抓兔。 放下布,搁下醋,上前去追鹰和兔, 飞了鹰,跑了兔。打翻醋,醋湿布。
老鼠嗅着油豆香 油一缸,豆一筐, 老鼠嗅着油豆香。 爬上缸,跳进筐, 偷油偷豆两头忙。 又高兴,又慌张, 脚一滑,身一晃, “扑通”一声跌进缸。
蚕和蝉 爬来爬去是蚕, 飞来飞去是蝉。 蚕常在桑叶里藏, 蝉藏在树林里唱。
八公庙里的八个和尚拿八根金箍棒打八个八哥儿,
不许八个八哥儿再到八公庙里的八棵白果树上做八个八歌儿窝。 虎和鼓 墙上挂面鼓,
鼓上画老虎,
老虎抓破鼓,
拿块布来补。
不知是布补鼓,
还是布补虎? 于琳琳爱捏泥 于琳琳爱捏泥,
揉揉泥,团团泥,
揉来揉去不起急。
捏了一只小狐狸,
又捏七只小小鸡。
小狐狸、小小鸡,
全都送给小弟弟。
钉钉棚棚上有钉,
棚钉钉钉钉钉棚。
帆船翻,翻帆船,竖起桅杆撑开帆。风吹帆,,帆引船,帆船顺风转海湾。 黄碗合活鸭
黄碗合活鸭。(念五遍)红鸡和灰鸡红鸡公尾巴灰,灰鸡公尾巴红。
宝宝掰,宝宝抱。
宝宝掰包谷包谷掉,
宝宝抱包谷宝宝笑。 瓜卖花 婆婆卖瓜又卖花,
一过卖来一边夸,
夸瓜大,夸花美,
人们买瓜又买花,
乐得婆婆笑哈哈。 喇嘛提蛤蟆、哑巴别着喇叭 打南边儿来了个喇嘛,
手里提着个蛤蟆,
打北边儿来了个哑巴,
腰里别着喇叭。
手里提蛤蟆的喇嘛,
要拿蛤蟆换哑巴腰里的喇叭;
腰里别喇叭的哑巴,
不拿喇叭换喇嘛手里的蛤蟆。
提蛤蟆的喇嘛,
打了哑巴一蛤蟆;
别喇叭的哑巴,
打了喇嘛一喇叭。
峰下枫。
峰上风吹蜂会飞,峰下枫,
峰下枫挡峰上风。破瓦和骡马 楼上一块破瓦,
楼下一匹骡马,
破瓦落下来打了骡马,
骡马跳起来踩了破瓦。老伯 郭老伯、骆第伯、毕老伯、柏老伯,
郭骆毕柏四老伯,约着城北买菱角,
买菱角阁上剥,菱角壳戳了四老伯了脚。
一个驼子,拉着车子;
一个瞎子,抱着孩子。
跛子的驴子,撞着驼子的车子;
驼子的车子,碰倒瞎子的孩子;
瞎子要打驼子,驼子要打跛子。 刘小牛去打油 刘小牛去打油,
买了油,往回走;
油瓶满,往外流,
多给了半斤油,
急坏了刘小牛。
多的油,不能留,
回到商店大退油;
叔叔摸摸小牛头,
阿姨拉拉小牛手,
齐声夸资刘小牛。 贾家养虾 贾家有女初出嫁,嫁到夏家学养虾,
喂养的对虾个头儿大,卖到市场直加价。
贾家爹爹会养鸭,鸭子虽肥伤庄稼。
邻里吵架不融洽,贾家也学养对虾。
小虾卡住了鸭子牙,大鸭咬住了虾的夹。
夏家公公劝,贾家爹爹压,大鸭不怕吓,
小虾装得嗲,夏家贾家没办法。
小宝宝年纪小。
老爷爷要看报,
小宝宝要吃糕。
老爷爷给宝宝拿糕,
小宝宝给爷爷拿报。
老爷爷看报眯眯笑,
小宝宝吃糕味道好。 红凤凰粉凤凰 红凤凰粉凤凰,
红粉凤凰粉红凤凰。
红凤凰粉凤凰,
红粉凤凰粉红凤凰!
油煎豆腐骨头多,
太湖当中挑野菜,
大山顶上摸田螺,
摸个田螺笆斗大,
摆了摇篮里骗外婆。 吃核桃 我敲桃壳你剥肉,
吃掉桃肉甩掉壳。
桃壳甩得门角落,
门角落头有桃壳。
天上看,满天星
天上看,满天星;
地下看,有个坑;
坑里看,有盘冰。
坑外长着—老松,松上落着一只鹰,
松下坐着一老僧,僧前放着—部经,
经前点着一盏灯,墙上钉着一根钉,
钉上挂着一张弓。说刮风,就刮风,
刮得男女老少难把眼睛睁。
刮散了天上的星,刮平了地的坑,
刮化了坑里的冰,刮倒了坑外的松,
刮飞了松上的鹰,刮走了松下的僧,
刮乱了僧前的经,刮灭了经前的灯,
刮掉了墙上的钉,刮翻了钉上的弓。
买来一桶油,跑来一头牛,
踢翻桶里油,牛角都是油。
天上看,满天星;地下看,有个坑;坑里看,有盘冰。坑外长着—老松,松上落着一只鹰,松下坐着一老僧
,僧前放着—部经,经前点着一盏灯,墙上钉着一根钉,钉上挂着一张弓。说刮风,就刮风,刮得男女老少
难把眼睛睁。刮散了天上的星,刮平了地的坑,刮化了坑里的冰,刮倒了坑外的松,刮飞了松上的鹰,刮走
了松下的僧,刮乱了僧前的经,刮灭了经前的灯,刮掉了墙上的钉,刮翻了钉上的弓。这是一段星散、坑平
、冰化、松倒、鹰飞、僧走、经乱、灯火、钉掉、弓翻的。
望月空满天星
望月空,满天星,光闪闪,亮晶晶,
好象那,小银灯,仔细看,看分明,
大大小小,密密麻麻,闪闪烁烁,数也数不清。
砸缸小光和小刚,抬着水桶上岗。
上山岗,歇歇凉,拿起竹竿玩打仗。
乒乒乒,乓乓乓,打来打去砸了缸。
小光怪小刚,小刚怪小光,小光小刚都怪丿竿和水缸。
隔着窗子撕字纸,一撕横字纸,
再撕竖字 纸,撕了四十四张湿字纸。
小猪扛锄头,吭哧吭哧走。
小鸟唱枝头,小猪扭头瞅,
锄头撞石头,石头砸猪头。
小猪怨锄头,锄头怨猪头。
老唐端蛋汤,踏凳登宝塔,
只因凳太滑,汤洒汤烫塔。
卖蒜的算卦,算卦的买蒜。
算卦的不买卖蒜的蒜,
卖蒜的不算算卦的卦。关于满天星的绕口令
抬头看,满天星,
低头看,一道坑。
坑里看,栽的葱,
葱上看,冻的冰。
屋里看,点着灯,
墙上看,钉的钉。
钉上看,挂的弓,
弓上看,卧的鹰。
寒冷天,刮大风,
刮散了,满天星。
刮平了,地下坑,
刮倒了,坑里葱。
刮消了,葱上冰,
刮灭了,屋里灯。
刮断了,墙上钉,
刮掉了,钉上弓;
刮飞了,弓上鹰。
这才是:星散、坑平葱倒
冰消、灯灭、钉断、弓掉、鹰飞。
得棒呛一场空。毛毛的红帽、猫猫的灰毛
毛毛有一顶红帽,
猫猫有一身灰毛。
毛毛要猫猫的灰毛,
猫猫要毛毛的红帽。
毛毛把红帽交给猫猫,
猫猫抽了几根灰毛送给毛毛。毛毛穿袍袍、苗苗戴帽帽一块追猫猫
毛毛穿袍袍,
苗苗戴帽帽。
毛毛和苗苗,
一块追猫猫。
猫猫喵喵叫,
急得蹦又跳。
猫猫抓破毛毛花袍袍,
猫猫抓破苗苗花帽帽。
苗苗给毛毛补袍袍,
毛毛给苗苗补帽帽。
树上的松鼠--蹿上跳下
树上的松鼠--蹿上跳下演员制服
男演员穿蓝制服,
女演员穿棉制服,
蓝制服是棉制服,
棉制服是蓝制服。
男演员穿蓝棉制服,
女演员穿棉蓝制服。
天上看,满天星
天上看,满天星;
地下看,有个坑;
坑里看,有盘冰。
坑外长着—老松,松上落着一只鹰,
松下坐着一老僧,僧前放着—部经,
经前点着一盏灯,墙上钉着一根钉,
钉上挂着一张弓。说刮风,就刮风,
刮得男女老少难把眼睛睁。
刮散了天上的星,刮平了地的坑,
刮化了坑里的冰,刮倒了坑外的松,
刮飞了松上的鹰,刮走了松下的僧,
刮乱了僧前的经,刮灭了经前的灯,
刮掉了墙上的钉,刮翻了钉上的弓。瘸子和矬子
小山屋
南面来了个瘸子,腰里别着个橛子,
北边来了个矬子,肩上挑着担茄子。
别橛子的瘸子要用橛子换挑茄子的矬子的茄子,
挑茄子的矬子不给别橛子的瘸子茄子。
别橛子的瘸子抽出腰里的橛子打了挑茄子的矬子一橛子,
挑茄子的矬子拿起茄子打了别橛子的瘸子一茄子。
好象那,小银灯,仔细看,看分明,
大大小小,密密麻麻,闪闪烁烁,
数也数不清。
补桶桐木桶,桶有洞,
补洞用桐不用铜。
用铜补洞补不住,
用桐补桶桶无洞。
聋童朦胧彩霓虹,
玲珑小聋童。
聋童采柠檬,
聋童不懵懂。
男演员穿蓝制服, 女演员穿棉制服, 蓝制服是棉制服, 棉制服是蓝制服。 男演员穿蓝棉制服, 女演员穿棉蓝制服。 【天上看,满天星】
天上看,满天星; 地下看,有个坑; 坑里看,有盘冰。 坑外长着—老松,松上落着一只鹰, 松下坐着一老僧,僧前放着—部经, 经前点着一盏灯,墙上钉着一根钉, 钉上挂着一张弓。说刮风,就刮风, 刮得男女老少难把眼睛睁。 刮散了天上的星,刮平了地的坑, 刮化了坑里的冰,刮倒了坑外的松, 刮飞了松上的鹰,刮走了松下的僧, 刮乱了僧前的经,刮灭了经前的灯, 刮掉了墙上的钉,刮翻了钉上的弓。
天上看,满天星; 地下看,有个坑; 坑里看,有盘冰。 坑外长着—老松,松上落着一只鹰, 松下坐着一老僧,僧前放着—部经, 经前点着一盏灯,墙上钉着一根钉, 钉上挂着一张弓。说刮风,就刮风, 刮得男女老少难把眼睛睁。 刮散了天上的星,刮平了地的坑, 刮化了坑里的冰,刮倒了坑外的松, 刮飞了松上的鹰,刮走了松下的僧, 刮乱了僧前的经,刮灭了经前的灯, 刮掉了墙上的钉,刮翻了钉上的弓。 【瘸子和矬子】
小山屋 南面来了个瘸子,腰里别着个橛子, 北边来了个矬子,肩上挑着担茄子。 别橛子的瘸子要用橛子换挑茄子的矬子的茄子, 挑茄子的矬子不给别橛子的瘸子茄子。 别橛子的瘸子抽出腰里的橛子打了挑茄子的矬子一橛子, 挑茄子的矬子拿起茄子打了别橛子的瘸子一茄子。
妈妈骂马妈妈种麻,我去放马,马吃了麻,妈妈骂马。
六叔和六舅好六叔和好六舅,借给六斗六升绿绿豆。打罢秋,接住豆,再还六叔六舅六斗六升绿绿豆。
小秋和小牛 小妞妞,叫小秋,梳着两个小抓鬏,小胖胖,叫小牛,穿着一个小兜兜。小秋帮着小牛记扣扣,小牛帮小秋剥豆豆,小秋、小牛手拉手,一块儿玩,一块儿走。
送 花华华有两朵红花,红红有两朵黄花,华华想要黄花,红红想要红花,华华送给红红一朵红花,红红送给华华一朵黄花。
好 孩 子张家有个小英子,王家有个小柱子。张家的小英子,自己穿衣洗袜子,天天扫地擦桌子,王家的小柱子,捡到一只皮夹子,还给后院大婶子。小英子,小柱子,他们都是好孩子。
任命、人名任命是任命,人名是人名,任命人名不能错,错了人名错任命。
四 老 伯郭老伯、骆老伯,毕老伯、柏老伯,郭骆毕柏四老伯,约着城北买菱角,买得菱角阁上剥,菱角壳戳了四老伯的脚。
分 果 果多多和哥哥,坐下分果果。哥哥让多多,多多让哥哥。都说要小个,外婆乐呵呵。
南南有个篮南南有个篮篮,篮篮装着盘盘,盘盘放着碗碗,碗碗盛着饭饭。南南翻了篮篮,篮篮扣了盘盘,盘盘打了碗碗,碗碗撒了饭饭。
瘸 子北边来了一个瘸子,背着一捆橛子。南边来了一个瘸子,背着一筐茄子。背橛子的瘸子打了背茄子的瘸子一橛子。背茄子的瘸子打了背橛子的瘸子一茄子。
小华和胖娃小华和胖娃,两人种花又种瓜,小华会种花不会种瓜,胖娃会种瓜不会种花,小华教胖娃种花,胖娃教小华种瓜。
白家伯伯北贫坡上白家有个伯伯,家里养着一百八十八只白鹅,门口种着一百八十八棵白果,树上住着一百八十八只八哥。八哥在白果树上吃白果,白鹅气得直叫:我饿!我饿!
白鸽尖尖红嘴壳,白鹅曲项向天歌。
白鸽剪开云朵朵,白鹅拨开浪波波。
鸽乐呵呵,鹅活泼波,白鹅白鸽碧波蓝天真快乐。小鱼大雁
小与入鱼网鱼网捕鱼鱼难逃,大雁过雁塔雁塔留雁雁不留。雾
早晨下大雾,山里看不见路,急坏了小猪、小兔和小鹿。
小兔领小猪,小猪拉小鹿,拉着藤,扶着树,一步一步走山路。
秋风婆婆来帮助,呼——呼——呼—— 一下吹散满天雾。猫吃桃河边有座窑,窑上有个槽,槽里放件袍,袍包个桃。
对岸有只猫,想吃窑上槽里袍包桃,可惜岸上没有桥。
过不了河,上不了窑,够不找槽,咬不住袍,吃不了桃。白庙、白猫、白帽山顶有座白庙,白庙里有只白猫。
白庙外有顶白帽,白猫看见了白帽,
叨着白帽跑进了白庙。牛和油买来一桶油,跑来一头牛,踢翻桶里油,牛角都是油。鼠吃豆和油鼠咬豆囤囤漏豆,鼠啃油篓篓漏油篓油,豆囤漏豆鼠啃豆,油篓漏油鼠吸油。
护 树北风吹摇路边树,小陆上前把树护。一个木竿路旁竖,一根绳子拴捆住。树有木竿做支柱,木竿支树树稳固。
石榴树上结辣椒颠倒话,话颠倒,石榴树上结辣椒。东西大路南北走,碰见兔子去咬狗。拿住狗,打砖头,砖头咬住我的手。
黑豆放黑斗黑豆放在黑斗里,黑斗里边放黑豆,黑豆放黑斗,黑斗放黑豆,不知黑豆放黑斗,还是黑斗放黑豆。
收 葵 花葵花、蓖麻胖娃小筐手中拿,来到园中收葵花;小华小篮身上挎,一同进园收蓖麻。胖娃种的葵花花盘大,小华种的蓖麻密麻麻。小华去帮胖娃摘葵花,胖娃去帮小华收蓖麻。小华和胖娃,收了葵花、蓖麻献国家。
荷花和蛤蟆一朵粉红大荷花,趴着一只活蛤蟆,八朵粉红大荷花,趴着八只活蛤蟆。
花 和 瓜瓜藤开花像喇叭,娃娃爱花不去掐。瓜藤开花瓜花结花,没花就没瓜。吃瓜要爱花,娃娃爱花也爱瓜。
白果树我从伯伯门前过,看见伯爹伯妈门前种着白果树,白果树上站着百十百个白斑鸠,我就拣了百十百块白石头,打那百十百个白斑鸠。
高高山上一条藤高高山上一条藤,藤条头上挂铜铃。风吹藤动铜铃动,风停藤停铜铃停。
一 捆 葱东边来个小朋友叫小松,手里拿着一捆葱。西边来个小朋友叫小丛,手里拿着小闹钟。小松手里葱捆得松,掉在地上一些葱。小丛忙放闹钟去拾葱,帮助小松捆紧葱。小松夸小丛像雷锋,小丛说小松爱劳动。
兜 装 豆兜里装豆,豆装满兜,兜破漏豆。倒出豆,补破兜,补好兜,又装豆,装满兜,不漏豆。
洪家地下有个棚,冯家房上有个瓶。 冯洪两家猫打架,弄倒了洪家的棚,打碎了冯家的瓶。 冯家要赔洪家的棚,洪家要赔冯家的瓶。 不知冯家要赔洪家的棚,还是洪家要赔冯家的瓶。碰碰车
碰碰车,车碰碰,坐着朋朋和平平。 平平开车碰朋朋,朋朋开车碰平平,不知是平平碰朋朋,还是朋朋碰平平。 东边一座楼
东边一座楼,楼上两人打拳头。 拳头打,打拳头。来了一个人,拉了一头牛,将牛拴在楼脚下,看他两人打拳头。 拳头打,打拳头。又来了一个人,领了一只猴,将猴放在牛脚下,看他两人打拳头。 拳头打,打拳头。又来了一个人,挑了一担油,将油放在猴脚下,看他两人打拳头。 拳头打,打拳头。又来了一个人,挑了一担绸,将绸放在油脚下,看他两人打拳头。 拳头打,打拳头,两人打垮车边楼。 垮子楼,压倒牛,牛一蹲,蹲倒猴,猴一抓,抓倒油,油一泼,泼上绸。 绸问油,卖油买绸来赔绸;油问猴,卖猴买油来赔油; 猴问牛,卖牛买猴来赔猴;牛问楼,卖楼买牛来赔牛。 只问绸扯油来油扯猴,猴扯牛来牛扯楼。猴子吃掉小桃子
树上有只小桃子,树下有只小猴子。风吹桃树哗哗响,树上掉下小桃子。 桃子打着小猴子,猴子吃掉小桃子。
嘴说腿,腿说嘴,嘴说腿爱跑腿,腿说嘴爱卖嘴。 光动嘴不动腿,光动腿不动嘴,不如不长腿和嘴。铜勺铁勺舀油
铜勺舀热油,铁勺舀凉油。铜勺舀了热油舀凉油,铁勺舀了凉油舀热油。 一勺热油一勺凉油,热油凉油都是由。 狗
南边来了他大大伯子家的大搭拉尾巴耳朵狗, 北边来了他二大伯子家的二搭拉尾巴耳朵狗。 他大大伯家的大搭拉尾巴耳朵狗,咬了他二大伯家的二搭拉尾巴耳朵狗一口; 他二大伯家的二搭拉尾巴耳朵狗,也咬了他大大伯家的大搭拉尾巴耳朵狗一口。 不知是他大大伯家的大搭拉尾巴耳朵狗,先咬了他二大伯家的二搭拉尾巴耳朵狗; 还是他二大伯家的二搭拉尾巴耳朵狗,先咬了他大大伯家的大搭拉尾巴耳朵狗。水连天
天连水,水连天,水天一色望无边。兰兰的天似绿水,绿绿的水如蓝天。 到底是天连水,还是水连天?
颠 倒 歌太阳从西往东落,听我唱个颠倒歌。天上打雷没有响,地上石头滚上坡。江里骆驼会下蛋,山上鲤鱼搭成窝。腊月炎热直流汗,六月寒冷打哆嗦。
妹照镜子头梳手,门外口袋把驴驮。青 龙 洞 青龙洞中龙做梦,青龙做梦出龙洞,做了千年万载梦,龙洞困龙在深洞。自从来了新愚公,愚公捅开青龙洞,青龙洞中涌出龙,龙去农田做农工。
造 房 子捡颗小石子,在地上画个方格子,画好了格子造房子,画个大方格子造个大房子,
画个小方格子造个小房子,楼上的房子分给鸽子,楼下的房子分给小兔子。搭 房 子红红的好朋友蓝蓝会搭红房子,蓝蓝的好朋友红红会搭蓝房子。会搭红房子的蓝蓝,愿帮会搭蓝房子的红红搭红房子,会搭蓝房子的红红,愿帮会搭红房子的蓝蓝搭蓝房子。
青 龙 洞青龙洞中龙做梦,青龙做梦出龙洞,做了千年万载梦,龙洞困龙在深洞。自从来了新愚公,愚公捅开青龙洞,青龙洞中涌出龙,龙去农田做农工。 皮鞋、蒲鞋一只皮鞋,一只蒲鞋,皮鞋补蒲鞋,蒲鞋补皮鞋,皮鞋、蒲鞋,蒲鞋、皮鞋……
盆 和 瓶桌上放个盆,盆里有个瓶,砰砰啪啪,啪啪砰砰,不知是瓶碰盆,还是盆碰瓶。河里有只船河里有只船,船上挂白帆,风吹帆张船向前,无风帆落停下船。
枪 和 糠墙上一个窗,窗上一支枪,窗下一箩糠。枪落进了糠,糠埋住了枪。窗要糠让枪,糠要枪上墙,墙要枪上窗。互相不退让,糠赶不走枪,枪也上不了窗和墙。比 锤炉东有个锤快锤,炉西有个锤锤快,两人炉前来比赛,不知是锤快锤比锤锤快锤得快?还是锤锤快比锤快锤锤得快?
簸箕簸玉米皮。
会簸簸箕能簸出玉米皮,
小波不会簸簸箕,
簸不出玉米皮。
后簸谷秕子。
会簸秕谷子,
就簸谷秕子。
不会簸秕谷子,
就不簸谷秕子。
簸完秕谷子,
再簸谷秕子。
簸箕簸灰簸箕簸灰,
风小灰回,
风大灰飞。
簸箕簸灰,
风大灰飞,
风小灰回。
我走白家门前过,
白家门前一棵白果树,
树上结了白果果,
白果树上歇了只白八哥。
高高山上一条藤,
藤条头上挂铜铃,
风吹藤动铜铃动,
风停藤停铜铃停。
拔萝卜
出八十八二十八,
八个小孩儿把萝卜拔,
你也拔,我也拔,
看谁拔得多,
看谁拔得大。
你拔得不多个儿不小,
我拔得不少个儿不大。
一个萝卜一个坑儿,
算算多少用车拉,
一个加俩,俩加仨,
七十二个加十八,
拿个算盘打一打,
一百差俩九十八。
吃菱角,剥菱壳,
菱角丢在北壁角。
不吃菱角不剥壳,
菱角不丢北壁角。采蘑菇
黑兔和白兔,
上山采蘑菇,
小猴和小鹿,
一齐来帮助,
猴和兔,兔和鹿,
高高兴兴采蘑菇。
桐子落,童子乐;
丫头啃鸭头,
鸭头咸,丫头嫌。朱叔锄竹笋朱家一株竹,
竹笋初长出,
朱叔处处锄,
锄出笋来煮,
锄完不再出,
朱叔没笋煮,
竹株又干枯。
八个八哥飞上树,八棱八角树上住。
树下孩子直发悉,手拿弹弓射大树。
打得八哥离开树,八棱八角掉下树。
吃葡萄青葡萄,紫葡萄,
青葡萄没籽葡萄紫,
吃葡萄不吐葡萄皮,
不吃葡萄倒吐葡萄皮。
棉花像雪花,雪花像棉花。
棉花不是雪花,雪花不是棉花,
冷冰冰的是雪花,暖烘烘的是棉花。
瓜卖花婆婆卖瓜又卖花,
一过卖来一边夸,
夸瓜大,夸花美,
人们买瓜又买花,
乐得婆婆笑哈哈。
低头捡豆,
豆捡在手,
豆装豆篓。瓜爸爸种瓜瓜儿大,
妈妈摘瓜摘大瓜,
奶奶切瓜分大家,
大家吃瓜笑哈哈。有豆有扣小篓篓,有豆豆还有扣扣,
娃娃想拿豆豆却拿起扣扣,
又想拿起扣扣却又拿起豆豆,
豆豆扣扣,都让娃娃放回篓篓。
葱和松
东院想栽葱,
西院想栽松。
是东院栽葱,
还是西院栽松。
半边莲,莲半边,
半边莲长在山涧边。
半边天路过山涧边,发现这片半边莲。
半边天拿来一把镰,割了半筐半边莲。
半筐半边莲,送给边防连。
瓜棚挂瓜
瓜棚挂瓜,瓜挂瓜棚。
风刮瓜棚瓜棚动,
棚动瓜动瓜碰棚。
水上漂着一只瓢,
水上漂着一只瓢,
瓢上落着一只鸟,
鸟看瓢,瓢瞪鸟,
鸟不认识瓢,瓢也不认识鸟。
花生生花
新生农业社,生产落花生。
花生生花生,花生花生生。
生了数百升,升升盛花生。
声声话花生,人人夸花生。
一捆葱
东边来个小朋友叫小松,
手里拿着一捆葱。
西边来个小朋友叫小丛,
手里拿着小闹钟。
小松手里葱捆得松,
掉在地上一些葱。
小丛忙放闹钟去拾葱,
帮助小松捆紧葱。
小松夸小丛像雷锋,
小丛说小松爱劳动。
代码如下:
1 | import requests |
执行结果如下:
存入文本中的数据如下:
网站如下:http://www.nows.fun/
1 |
|
代码如下:
1 | import requests |
执行结果如下图:


加了去重,钉钉报警
db.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53# -*- encoding: utf-8 -*-
import hashlib
import time
from sqlalchemy import create_engine
from sqlalchemy import Column, VARCHAR, Integer, TIMESTAMP, CHAR
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('mysql+pymysql://root:123456@localhost/test?charset=utf8')
DBSession = sessionmaker(bind=engine)
session = DBSession()
Base = declarative_base()
class YoududuanziItem(Base):
"""段子信息"""
__tablename__ = 'duanzi_for_fun'
desc = '段子信息'
id = Column(Integer, primary_key=True, autoincrement=True)
duplicate_hash = Column(CHAR(40), index=True, unique=True, doc={'zh': "url hash"})
crawl_time = Column(TIMESTAMP, doc={'zh': '当前时间'})
centence = Column(VARCHAR(200), index=True, doc={'zh': '段子'})
@classmethod
def creat_table(cls):
"""创建数据表"""
cls.__table__.create(bind=engine, checkfirst=True)
def insert(self, centence):
url_sha = self.get_contern_url_hash(centence)
crawled_time = time.strftime('%Y-%m-%d %H:%M:%S')
try:
is_exist = session.query(YoududuanziItem).filter(YoududuanziItem.duplicate_hash == url_sha).all()
if not is_exist:
item = YoududuanziItem(duplicate_hash=url_sha, crawl_time=crawled_time, centence=centence)
session.add(item)
session.commit()
return True
else:
return False
except BaseException as e:
session.rollback()
session.close()
raise BaseException(f"数据插入失败: \n{url_sha} \n{centence} \n{e}")
def get_contern_url_hash(self, content_url):
hash = hashlib.sha1()
hash.update(str(content_url).encode('utf-8'))
url_sha = hash.hexdigest()
return url_sha
爬虫代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81# -*- encoding: utf-8 -*-
import time
import json
import requests
import logging
from lxml import etree
from fake_useragent import UserAgent
from my_test.db import session, YoududuanziItem
class YoududuanziSpider(object):
def __init__(self):
self.headers = {
'User-Agent': self.get_random_ua()
}
self.url = 'http://www.nows.fun/'
# 钉钉报警模板字段,注意: 必须使用raw string, 不能使用多行字符串, 钉钉只处理没有转义的字符, 包含转义字符会导致解析失败
self.failure_template = ('数据爬取信息:\n\n'
'> spider_name: {spider_name}\n\n'
'> table_name: {table_name}\n\n'
'> data_num: {data_num}\n\n'
'> last_data: {last_data}\n\n'
'> log_url: {log_url}\n\n')
self.dingding_headers = {
"Content-Type": "application/json;charset=utf-8",
}
def get_random_ua(self): # 随机UA
ua = UserAgent()
return ua.random
def get_content(self):
response = requests.get(url=self.url, headers=self.headers, timeout=10)
selector = etree.HTML(response.text)
centence = selector.xpath('//span[@id="sentence"]/text()')[0]
return centence
def send_dingtalk(self, spider_name, table_name, data_num, last_data, log_url):
try:
content = self.failure_template.format(
spider_name=spider_name,
table_name=table_name,
data_num=data_num,
last_data=last_data,
log_url=log_url
)
msg = {
"msgtype": "markdown",
"markdown": {
"title": '爬取的段子信息',
"text": '淘数爬虫:' + content
}
}
ding_url = 'https://oapi.dingtalk.com/robot/send?access_token=c1984aefbaff584bceb37b855b8380d7c6c78545fb749d068fc378df627fa786'
resp = requests.post(url=ding_url, headers=self.dingding_headers, data=json.dumps(msg), timeout=30)
json_data = json.loads(resp.text)
if resp.status_code == 200 and json_data['errcode'] == 0:
pass
else:
logging.error('钉钉报警发送失败{}'.format(json_data['errmsg']))
except Exception as e:
logging.error("send dingtalk failed, exception: ", e)
def run(self):
for i in range(100000):
job_info = self.get_content()
table.insert(job_info)
time.sleep(2)
if i % 1000 == 0:
logging.info(f'爬取进度:self.num={i}条数据!!!')
self.send_dingtalk(spider_name='youduduanzi', table_name='duanzi_for_fun', data_num=5, last_data=job_info, log_url=self.url)
if __name__ == '__main__':
duanzi = YoududuanziSpider()
table = YoududuanziItem()
table.creat_table()
duanzi.run()
共勉,(๑•̀ㅂ•́)و✧加油
设计模式:代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
GOF介绍:在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。
四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。
总的来说设计模式分为3大类:
• 创建型模式(Creational Patterns):(都是用来帮助我们创建对象的)这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。主要包括:
单例模式(Singleton Pattern):保证一个类仅有一个对象,并提供一个访问它的全局访问点。(Ensure a class only has one instance,and provide a globe point of access to it.)
详细单例模式介绍可点此链接:单例模式详解(附常见的7种单例模式源码)
用Python实现单例模式:用Python 实现单例模式 (Python经典编程案例)
工厂模式(Factory Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化,FactoryMethod使一个类的实例化延迟到其子类。(Define an interface for creating anobject, but let subclasses decide which class to instantiate. Factory methodlets a class defer instantiation to subclasses.)
详细工厂模式介绍可点此链接:工厂模式详解 (附java语言源码)
Python实现工厂模式:用python实现工厂设计模式(Python经典编程案例)
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。(Provide an interface for creating families of related or dependent object without specifying their concrete classes.)
详细抽象工厂模式介绍可点此链接:抽象工厂模式详解 (附java语言源码)
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。(Separate the construction of a complex object from its representation so that the same construction process can create different representations.)
详细建造者模式介绍可点此链接:建造者模式详解 (附java语言源码)
原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。(Specify the kinds of objects to create using a prototypical instance, and create new objects by copying the prototype.)
详细原型模式介绍可点此链接:原型模式详解 (附java语言源码)
•结构型模式(Structural Patterns):这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。主要包括:
适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。(Convert the interface of a class into another interface clients except. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.)
详细适配器模式介绍可点此链接:适配器模式详解 (附java语言源码)
桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使他们都可以独立地变化。(Decouple an abstraction from its implementation so that the two can vary independently.)
详细桥接模式介绍可点此链接:桥接模式详解 (附java语言源码)
装饰模式(Decorator Pattern):动态地给一个对象添加一些额外的职责。就扩展功能而言,Decorator模式比生成子类的方式更为灵活。(Attach additional responsibilities to an object dynamically. Decorators provides a flexible alternative to subclasses for extending functionality.)
详细装饰模式介绍可点此链接:装饰模式详解 (附java语言源码)
组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构。Composite 使得客户对单个对象和复合对象的使用具有一致性。(Compose object into tree structures torepresent part-whole hierarchy. Composite lets clients treat individual objectsand compositions of objects uniformly.)
详细组合模式介绍可点此链接:组合模式详解 (附java语言源码)
外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的接口。Façade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。(Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.)
详细外观模式介绍可点此链接:外观模式详解 (附java语言源码)
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象。(Use sharing to support large numbers offine-grained objects efficiently.)
详细享元模式介绍可点此链接:享元模式详解 (附java语言源码)
代理模式(Proxy Pattern):为其他对象提供一个代理以控制对这个对象的访问。(Provide a surrogate or placeholder foranther object to control access to it.)
详细代理模式介绍可点此链接:代理模式详解 (附java语言源码)
• 行为型模式(Behavioral Patterns):这些设计模式特别关注对象之间的通信。主要包括:
模版方法模式(Template Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。(Define the skeleton of an algorithm inan operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing thealgorithm’s structure.)
详细模版方法模式介绍可点此链接:模板方法模式详解 (附java语言源码)
命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可取消的操作。(Encapsulate a request as an object,thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.)
详细命令模式介绍可点此链接:命令模式详解 (附java语言源码)
迭代器模式(Iterator Pattern):提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。(Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.)
详细迭代器模式介绍可点此链接:迭代器模式详解 (附java语言源码)
观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。(Define a one-to-many dependency between objects so that when one object changes state all its dependents are notified and updated automatically.)
详细观察者模式介绍可点此链接:观察者模式详解 (附java语言源码)
中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。(Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly and it lets you vary their interaction independently.)
详细中介者模式介绍可点此链接:中介者模式详解 (附java语言源码)
备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保持该状态,这样以后就可以将该对象恢复到保存的状态。(Without violating encapsulates, captureand externalize an object’s internal state so that the object can be restored to this state later.)
详细备忘录模式介绍可点此链接:备忘录模式详解 (附java语言源码)
解释器模式(Interpreter Pattern):定义一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。(Given a language, define are presentation for its grammar along with an interpreter that uses there presentation to interpret sentences in the language.)
详细解释器模式介绍可点此链接:解释器模式详解 (没有附java语言源码)
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。(Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.)
详细状态模式介绍可点此链接:状态模式详解 (附java语言源码)
策略模式(Strategy Pattern):定义一系列的算法,把它们一个个封装起来,并且使他们可相互替换。本模式使得算法的变化可以独立于使用它的客户。(Define a family of algorithms,encapsulate each one and make them interchangeable. Strategy lets the algorithmvary independently from clients that use it.)
详细策略模式介绍可点此链接:策略模式详解(用java语言实现策略模式)
责任链模式(Chain of Responsibility Pattern):为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它。(Avoid coupling the sender of a requestits receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until anobject handles it.)
详细责任链模式介绍可点此链接:责任链模式详解 (附java语言源码)
访问者模式(Visitor Pattern):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类别的前提下定义作用于这些元素的新操作。(Represent an operation to be performedon the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.)
详细访问者模式介绍可点此链接:访问者模式详解 (没有附java语言源码)
此外还有一些J2EE模式:这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
下面用一个图片来整体描述一下设计模式之间的关系:
谢谢
安装 :
pip install pyinstaller==3.4
安装即可
PyInstaller 命令基本语法:
pyinstaller [options] script[script ...]|specfile
pyinstaller test.py
1 | 常规 |
基本用法
假定Python项目的主函数入口为main.py,则打包命令如下
pyinstaller -F main.py
-F参数大小写敏感
指定搜索路径,若有多个模块搜索路径需要指明
pyinstaller -F main.py -p /usr/local/python3/bin/python3 -p ./package
文档链接
https://media.readthedocs.org/pdf/pyinstaller/stable/pyinstaller.pdf
升级模块:pip install –upgrade 库名
官方参考:https://packaging.python.org/tutorials/packaging-projects/
参考文章:https://mp.weixin.qq.com/s/IZJfkfgDWSGNhuUJn6wRoQ
我的:https://pypi.org/ cuiyonghua cui1-A!
https://github.com/wistbean/learn_python3_spider
/Users/cuiyonghua/Desktop/my_work_files/softwares/mongodb/mongodata/etc/mongo.conf
init1
2
3
4from __future__ import absolute_import
from .xiaocui import *
name = "xiaocui"
xiaocui.py1
2
3
4
5
6
7
8
9
10
11
12# -*- coding: utf-8 -*-
def output():
print('hello,这是')
def output1(data):
print('hello,这是:{}'.format(data))
def susu(susu):
print('susu:{}'.format(susu))
setup.py:
这个文件主要是要告诉 setuptools ,我们的包里面的一些信息,比如名称啊,版本号啊,作者,邮箱等等1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# -*- coding: utf-8 -*-
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="xiaocui",
version="0.0.1",
author="xiaocui",
author_email="cui_yonghua6@163.com",
description="This is an cui package, fa li wu bian",
long_description=long_description,
long_description_content_type="text/markdown",
keywords="hello world example examples",
url="https://github.com/cuiyonghua6/cui_package",
packages=setuptools.find_packages(),
classifiers=[
'Programming Language :: Python :: 3',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
]
)
LICENCE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21MIT License
Copyright (c) 2020 cuiyonghua6
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
python3 -m pip install –user –upgrade setuptools wheel
python3 setup.py sdist bdist_wheel
https://pypi.org/account/register/
https://test.pypi.org/account/register/
python3 -m pip install –user –upgrade twine
(apt install twine)
python3 -m twine upload dist/*
1 | --name 包名称 |
下列entry_points中: console_scripts 指明了命令行工具的名称;在“redis_run = RedisRun.redis_run:main”中,等号前面指明了工具包的名称,等号后面的内容指明了程序的入口地址。1
2
3entry_points={'console_scripts': [
'redis_run = RedisRun.redis_run:main',
]}
1 |
|
标签(空格分隔): python PEP8 代码 规范
在日常工作中,编写python代码时,大家有可能因为IDE的不同或者是没有遵循python的pep8规范而导致每个人的格式都不尽相同,导致其他人阅读起来比较吃力。但是有时候代码规范也并不是建议使用的,最主要的是风格一致性,每个组内的代码风格统一起来才是最重要的,根据自己的判断选择是否遵循PEP8。
ps: 许多项目有自己的编码规范,在出现规范冲突时,项目自身的规范优先。
接下来我们只挑一些在工作中频繁遇到规范进行示例,为减少大家阅读时间,以 推荐 和 糟糕 来说明。
每一级缩进使用4个空格。
推荐:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26# 与左括号对齐
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 用更多的缩进来与其他行区分
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# 挂行缩进应该再换一行
foo = long_function_name(
var_one, var_two,
var_three, var_four)
# 与内容对齐
my_list = [
1, 2, 3,
4, 5, 6,
]
# 与第一行第一个字符对齐
my_list = [
1, 2, 3,
4, 5, 6,
]
糟糕:1
2
3
4
5
6
7
8
9
10
11# 没有使用垂直对齐时,禁止把参数放在第一行
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 当缩进没有与其他行区分时,要增加缩进
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
my_list = [1, 2, 3, 4, 5, 6]
所有行限制的最大字符数为79。
推荐:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 类与类之间前后用两个空行隔开
Class A:...
Class B:...
# 类中函数与函数之间前后用一个空行隔开
Class C:
def c_a(self):...
def c_b(self):...
# 函数与函数之间前后用两个空行隔开
def a_run():...
def b_run():...
# 在函数中使用空行来区分逻辑段(谨慎使用)。
def c_run():
# 逻辑A
...
...
# 逻辑B
...
...
推荐:
同时在每一组导入之间加入空行。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 官方标准库导入
import os
import sys
# 第三方库
import arrow
import requests
# 导入本地库
import app
# 以from导入标准库
from datetime import datetime
# 以from导入第三方库
from ldap3 import Server
# 以from导入本地库
from app import DB
from . import create_app # 处理绝对路径过长时可以以相对路径进行替换
糟糕:1
2# 在import中导入多个库
import sys, os
二元运算符中的空格:
推荐:1
2
3
4
5
6
7
8
9i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
糟糕:1
2
3
4
5
6
7
8
9i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
关键字参数或者默认参数值:
推荐:1
2def complex(real, imag=0.0):
return magic(r=real, i=imag)
糟糕:1
2def complex(real, imag = 0.0):
return magic(r = real, i = imag)
当更新代码时,一定要记得同步更新注释,否则使阅读的人会陷入更糟糕的近况。
推荐:1
2
3
4"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
大家在写函数或者方法时,往往会漏掉当前方法或函数的作用,其实这个还是很重要的,这样往往不需要阅读你的逻辑就可以知道你准备干什么
推荐:1
2
3
4
5
6
7
8
9
10
11
12"""
def oa_notice_template(project, api, account, cpu, mem):
"""
压测申请模板
:param project: 项目名称
:param api: 接口名称
:param account: 申请人
:param cpu: cpu核数
:param mem: 内存大小
:return:
"""
"""
在编写代码时,阅读者追寻编写人时往往很困难,或者此文件具体是做什么的。这个时候我们稍微添加一些个人信息注释就很好做到追源了。
推荐:1
2
3
4
5
6
7
8
9
10"""
@Description: 接口测试上传
@Author : duanfei
@Time : 2020/5/9 11:51 下午
@Site :
@File : http_test.py
"""
import os
...
命名规范很重要,很多时候你的命名能够大致的解释了变量、函数、类是用来做什么的。所以在命名的时候一定要选择贴近的词义,让阅读者可以理解
模块应该用简短全小写的名字,如果为了提升可读性,下划线也是可以用的。Python包名也应该使用简短全小写的名字,但不建议用下划线。
类名一般使用单词首字母大写的约定
推荐:1
class CheckFunc:...
糟糕:1
2
3
4
5
6# 首字符需大写,同时类名中无需带下划线
class check_func:...
# 全部大写,同时类名中无需带下划线
class CHECK_FUNC:...
函数名应该小写,如果想提高可读性可以用下划线分隔。
推荐:1
def check_func():...
一定要靠近变量的意思,不要使用一些意义不明的参数,如:i,j,k,特别注意永远不要使用字母‘l’(小写的L),‘O’(大写的O),或者‘I’(大写的I)作为单字符变量名。
糟糕:1
2
3
4
5l = []
i = 0
xxx = [for i in xx]
常量一般默认全部为大写, 同时一定要表明好注释
推荐:1
2
3
4TOTAL = 10 # 订单总页数
# 最大溢出量
MAX_OVERFLOW = 1000
因为异常一般都是类,所有类的命名方法在这里也适用。
推荐:1
2
3
4
5
6
7
8class ErrorInvalidArgument(ApiError):
"""
参数缺失或错误
"""
code = 401001
code_name = 'Invalid_Argument'
message = 'invalid argument.'
zh_message = '参数缺失或错误'
关于异常处理:
推荐:1
2
3
4
5
6try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
糟糕:1
2
3
4try:
return handle_value(collection[key])
except KeyError:
return key_not_found(key)
关于返回结果处理:
不管在任何时候返回结果都需要保持一致。
推荐:1
2
3
4
5
6
7
8
9
10def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
def bar(x):
if x < 0:
return None
return math.sqrt(x)
糟糕:1
2
3
4
5
6
7
8def foo(x):
if x >= 0:
return math.sqrt(x)
def bar(x):
if x < 0:
return
return math.sqrt(x)
关于True、Fakse的判断:
不要用 == 去和True或者False比较
推荐:1
2if greeting:
...
糟糕:1
2
3
4
5if greeting == True:
...
if greeting is True:
...
==================================================
规范—新手村(孙晓飞)
相信现代编译器的bug是很难遇到的
也就是说,当你的程序出现bug的时候,最后去怀疑编译器和系统(windows除外)
mr要有意义
最大也是最重要的原因是——在采用squash合入master的时候,mr的title会作为这次merge的commit信息,没有意义的mr==没有意义的commit。那么,为什么commit要有意义呢……去面壁吧,不说这个问题了……
不明白的代码,不要乱用!
不明白的代码,不要乱用! 不明白的代码,不要乱用! OK我说了三遍了
不要有过多输出
尤其是你开发的是一个包会被别人调用的情况下,因为别人连关都关不掉
没有经过profile过的程序做瓶颈优化都是耍流氓
profile的方法参见:(假装有东西,等写完放过来)
万恶之源
有的人说重复代码是万恶之源,有的人说过早的重构(或优化)是万恶之源 这两种说法虽然是矛盾的,但是都说出了部分的真相——我个人的偏好是:1
2
3
4
5
6
7
8
9
10
11
12
13if 存在重复代码 {
if 不需要使用interface(go和java里的interface,python里的抽象类,c++里的模板)就可以解决{
do 干他!
} else {
if 处于项目早期 {
项目优先
} else {
do 干他!
}
}
} else {
print(“大侠再见”)
}
尊重IDE
最重要的是尊重编译器的warning
代码不要给其他人造成心智负担
包括但不仅限于:
merge后的分支需要删除,无论本地还是远端,都要删除
不要用注释代码的方式保留老代码;注释要有意义
使用正确的变量名
(Python)使用variable annotation
减少中文的使用
包括但不仅限于,中文文档、CSDN、百度搜索等等
PyCharm 的doc string采用google style
原因包括但不仅限于:
不然的话会在群里看到自己要请大家喝奶茶的消息 :)
termius (windows用户强制,会折腾microsoft terminal的请忽略我)
source tree (mac和windows)ShannonWIKI
PyCharm的save action插件,在save的时候选择reformat以及optimize
GoLand的File Watchers里启用go fmt
每个项目都要要设置line seperator为Unix模式,也就是使用\n。windows用户要尤其注意。
除非你厉害,否则不要用vim或者emacs,人类发明很多工具是有理由的
使用IDE做VCS
绝对路径,之前提过了
除了config文件,项目中绝对不准使用绝对路径!!!!!!!
在任何地方,都不允许使用linux的相对路径,也就是”../“这种形式
解释一下正确做法:
项目中,数据分为两种:一种是不需要外部传入的数据,这类数据的路径一定是相对于项目根目录的路径的,具体做法是用Python的函数获取项目的路径,然后其他素有路径都是相对于这个录几个的;另一种是外部挂载的数据,一般是是大数据或者敏感数据,这类是将路径写在config中,然后将config忽略来做到的
不允许绝对路径,不允许赤裸裸的相对路径!!!!!!!!!!!!!!!
python代码,如果参数过多需要换行,建议采用这种形式:1
2
3
4
5function(
para_1,
para_2,
…
)
而不是:1
2
3function(para_1,
para_2,
…)
更不能:1
2
3function(para_1,
para_2
)
不要乱用字典
各位,很严肃的提醒,字典(python里的dict,go、C++、java里的map)这种数据结构,适用于存储key-value结构,而且是key不定的情况,如果key是确定的,最好声明一个类来存储,否则代码维护性极差,我们之前已经吃过亏了,不要再吃亏了。因此,以后如果key是确定的情况,严禁使用字典作为传参手段,尤其是python,不要把编程语言的字典当成json来用。
git的开发规范
从master上,新建分支,然后做修改,commit,push,远端merge后,checkout到master,然后拉取远端,然后进入下一轮开发。严禁在master上做修改,然后checkout到新分支,然后提交!!!!
source activate conda_venv
conda activate conda_venv
source deactivate
1、首先在所在系统中安装Anaconda。可以打开命令行输入conda -V检验是否安装以及当前conda的版本。
2、conda常用的命令。
1)conda list 查看安装了哪些包。
2)conda env list 或 conda info -e 查看当前存在哪些虚拟环境
3)conda update conda 检查更新当前conda
3、创建python虚拟环境。
使用 conda create -n your_env_name python=X.X(2.7、3.6等)命令创建python版本为X.X、名字为your_env_name的虚拟环境。your_env_name文件可以在Anaconda安装目录envs文件下找到。
4、使用激活(或切换不同python版本)的虚拟环境。
打开命令行输入python --version可以检查当前python的版本。
使用如下命令即可 激活你的虚拟环境(即将python的版本改变)。
Linux: source activate your_env_name(虚拟环境名称)
Windows: activate your_env_name(虚拟环境名称)
这是再使用python –version可以检查当前python版本是否为想要的。
5、对虚拟环境中安装额外的包。
使用命令conda install -n your_env_name [package]即可安装package到your_env_name中
6、关闭虚拟环境(即从当前环境退出返回使用PATH环境中的默认python版本)。
使用如下命令即可。
Linux: source deactivate
Windows: deactivate
7、删除虚拟环境。
使用命令conda remove -n your_env_name(虚拟环境名称) –all, 即可删除。
8、删除环境中的某个包。
使用命令conda remove –name your_env_name package_name 即可。
1 | import turtle as t |
1 | import turtle |
代码如下:
1 | import turtle |
执行结果如下图:
1 | import turtle |
excel格式:https://www.cnblogs.com/fkissx/p/5617630.html
1 |
|
1 |
|
使用的是:pandas.DataFrame.to_excel
使用create_engine()实现连接,需要了解create_engine()各个参数的作用1
2
3
4
5# 连接数据库
from sqlalchemy import create_engine
engine = create_engine(
"mysql+pymysql://root:1990@localhost:3306/crawl_test?charset=utf8",
echo=True)
定义实体映射类数据表结构,通过操作类属性从而操作数据表字段
创建表结构的方式
创建一个自增的数字主键!!!:不需要特意的设定,SQLAlchemy will automatically set the first Integer PK column that’s not marked as a FK as autoincrement=True
1 | # 创建数据表方法一 |
1 | # 创建数据表方法二 |
删除数据表:1
2
3# 删除数据表
StudentItem.drop(bind=engine)
Base.metadata.drop_all(engine)
引入sessionmaker模块,绑定已连接数据库的engin对象,生成会话对象session
对实体类的属性赋值,通过session.add()方法添加数据,通过session.commit()方法提交数据。1
2
3
4new_data = mytable(name='Li Lei',age=10,birth='2017-10-01',class_name='一年级一班')
session.add(new_data)
session.commit()
session.close()
先查询需要修改的数据对象再更新,更新方法有修改对象属性值 和 使用update()方法更新数据。1
2
3session.query(mytable).filter_by(id=1).update({ mytable.age : 12})
session.commit()
session.close()
1 | session.query(mytable).filter_by(id=1).delete() |
filter_by相当于SQL语句里面的where判断;
join相当于SQL语句中的inner join ;
outerjoin相当于full outer join ;
1、查询myclass全部数据1
2
3
4
5
6
7
8
9
10
11
12
13
14# 查询myclass全部数据,相当于select * from myclass;
# all()是将数据以列表的形式返回
get_data = session.query(myclass).all()
for i in get_data:
print('我的名字是:' + i.name)
print('我的班级是:' + i.class_name)
session.close()
# 查询某些字段,相当于select name, class_name from myclass;
get_data = session.query(myclass.name, myclass.class_name).all()
for i in get_data:
print('我的名字是:' + i.name)
print('我的班级是:' + i.class_name)
session.close()
2、设置筛选条件
filter和filter_by
1 | # 根据条件查询某条数据 |
把all()换成first()可以查询1条数据:1
2# 查询id为1的数据
single_stu = session.query(StudentItem).filter_by(stu_id=stu_id).first()
3、设置多筛选条件:
带and的查询,如:select * from mytable where id>1 and class_name=’三年级二班’,代码如下:1
2
3
4
5get_data = session.query(mytable).filter(mytable.id >= 2,
mytable.class_name == '三年级二班').first()
print('数据类型是:' + str(type(get_data)))
print('我的名字是:' + get_data.name)
print('我的班级是:' + get_data.class_name)
带or的查询,如:select * from mytable where id>1 and class_name=’三年级二班’,代码如下:1
2
3
4
5
6from sqlalchemy import or_
get_data = session.query(mytable).filter(or_(mytable.id >= 2,
mytable.class_name == '三年级二班')).all()
print('数据类型是:' + str(type(get_data)))
print('我的名字是:' + get_data.name)
print('我的班级是:' + get_data.class_name)
涉及多表查询的内连接查询和外连接查询:1
2
3
4
5
6
7
8
9# 内连接
get_data = session.query(mytable).join(myclass).filter(mytable.class_name == '三年级二班').all()
print('数据类型是:' + str(type(get_data)))
for i in get_data:
print('我的名字是:' + i.name)
print('我的班级是:' + i.class_name)
# 外连接
get_data = session.query(mytable).outerjoin(
myclass).filter(mytable.class_name == '三年级二班').all()
4、涉及复杂的查询语句,特别涉及多表查询和复杂的查询条件时,可直接执行sql语句:1
2
3
4sql = 'select * from mytable '
session.execute(sql)
# 如果涉及更新,添加数据,需要session.commit()
session.commit()
1 | # -*- encoding: utf-8 -*- |
sqlalchemy_test.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111from sqlalchemy.orm import sessionmaker
from crawl_test.orm import Base, engine, StudentItem
get_session = sessionmaker(bind=engine) # 可设置autocommit=True 对当前session进行设置
session = get_session()
def create_table(engine):
"""创建表"""
Base.metadata.create_all(engine)
def add_one():
"""向表中添加数据"""
try:
new_data = StudentItem(stu_name='王五', stu_age=30, stu_birth='2005-06-09', stu_class_name='六年级4班')
session.add(new_data)
session.commit()
print('向表中添加单条数据成功')
session.close()
except Exception as e:
session.rollback()
raise Exception(f'向数据库添加数据失败 :{e}')
def query_one(stu_id=None, stu_name=None):
"""根据id或者名字查询,返回字典"""
try:
if stu_id:
single_stu = session.query(StudentItem).filter_by(stu_id=stu_id).first()
else:
single_stu = session.query(StudentItem).filter_by(stu_name=stu_name).first()
single_stu_dict = single_stu.__dict__
return single_stu_dict
except Exception as e:
session.rollback()
raise Exception(f'数据库查询失败 :{e}')
finally:
session.close()
def query_all():
"""查询所有数据,返回一个列表"""
stu_data_list = []
try:
stu_data = session.query(StudentItem).all()
# 遍历对象的列表,并转换成字典
for stu in stu_data:
stu_dict = stu.__dict__
stu_data_list.append(stu_dict)
return stu_data_list
except Exception as e:
session.rollback()
raise Exception(f'数据库查询失败 :{e}')
finally:
session.close()
def update_stu_data(stu_id=None, stu_name=None, stu_data_dict=None):
"""根据id或者名字来修改数据"""
try:
if stu_id:
result = session.query(StudentItem).filter_by(stu_id=stu_id).update(stu_data_dict)
else:
result = session.query(StudentItem).filter_by(stu_name=stu_name).update(stu_data_dict)
print('修改成功', result)
session.commit()
session.close()
except Exception as e:
session.rollback()
raise Exception(f'修改数据失败 :{e}')
def delete_stu_data(stu_id=None, stu_name=None):
"""删除一个数据"""
try:
if stu_id:
ret = session.query(StudentItem).filter(StudentItem.stu_id == stu_id).delete()
else:
ret = session.query(StudentItem).filter(StudentItem.stu_name == stu_name).delete()
print('删除成功', ret)
session.commit()
session.close()
except Exception as e:
session.rollback()
raise Exception(f'删除数据失败 :{e}')
if __name__ == "__main__":
# create_table(engine)
# 增加一个数据
# add_one()
# 查询:根据id或者姓名查询单个数据
stu_data = query_one(stu_id=6)
print(stu_data['stu_name'])
# 查询:所有数据
# stu_data_list = query_all()
# for stu_data in stu_data_list:
# print(stu_data)
# 更新数据
# data_dict = {
# StudentItem.stu_age: 42,
# StudentItem.stu_name: '张君宝'
# }
# update_stu_data(stu_name='张无忌', stu_data_dict=data_dict)
# 删除数据
# delete_stu_data(stu_id=3)
1、创建一个schema:1
2
3
4
5
6
7
8
9Base = declarative_base() #生成orm基类
class AlchemyTest(Base):
__tablename__ = 'tbSqlAlchemyTest' #这里不用加上dbo.前缀,默认已经有了
TestName = Column(String(256), primary_key=True)
TestNumber = Column(INTEGER)
#the table object is a member of a larger collection known as MetaData
Base.metadata.create_all(engine) #通过基类与数据库进行交互创建表结构,此时表内还没有数据
还可以在创建class的末尾加上类似于:1
2
3def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (
self.name, self.fullname, self.password)
这个为可选项,只是增加对于表的描述,便于以后测试
向表内加入数据:
先创建一个实例:test1 = AlchemyTest(TestName='user1', TestNumber=1995)
再创建一个会话:1
2
3
4
5
6
7
8from sqlalchemy.orm import sessionmaker
Session_class = sessionmaker(bind=engine) #建立与数据库的会话连接,这里建立的是一个class不是一个实例对象
session = Session_class() #这里创建一个会话实例
test1 = AlchemyTest(TestName='user1', TestNumber=1995)
session.add(test1) #把要创建的数据对象加入到这个会话中,这个时候是pending状态,添加多个对象使用add_all()
session.commit() #统一提交会话中的操作
session.close()
在提交这个会话之前就可以使用:our_user = session.query(User).filter_by(name='ed').first() 来查看刚刚创建的数据
在会话提交之前,还可以这样回滚这个会话,使之前flush的内容失效: session.rollback()
每个session会话才是真正的与数据库的连接
2、建立表与表之间的关系(一对多,多对一):
多对一:employee对于department是多对一的关系1
2
3
4
5
6
7
8
9
10
11class Department(Base):
__tablename__ = 'department'
id = Column(Integer, primary_key=True)
name = Column(String(30))
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
name = Column(String(30))
dep_id = Column(Integer, ForeignKey('department.id'))
department = relationship("Department")
一对多:department对于employee是一对多的关系1
2
3
4
5
6
7
8
9
10
11class Department(Base):
__tablename__ = 'department'
id = Column(Integer, primary_key=True)
name = Column(String(30))
employees = relationship("Employee")
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
name = Column(String(30))
dep_id = Column(Integer, ForeignKey('department.id'))
新建一个tbSqlAlchemyTestError的table 一个test可以有多个error1
2
3
4
5
6
7
8
9
10
11
12
13
14class AlchemyTestError(Base):
__tablename__ = 'tbSqlAlchemyTestError'
errorID = Column(INTEGER, primary_key=True)
errorname = Column(String(256), nullable=False)
TestName = Column(String(256), ForeignKey('tbSqlAlchemyTest.TestName'))#这里面关联外键使用表的名字而不是类的名字,表与表之间建立联系
test = relationship("AlchemyTest", back_populates="error")
#告诉ORM,自己这个class与AlchemyTest这个class相关联,并且设定了一个“多对一”的关系
#*在自己这个类中生成一个test属性,然后在AlchemyTest类中创建一个error属性,与之关联,可以反向查询*
AlchemyTest.error = relationship("AlchemyTestError", back_populates="test")
#与上面一个relationship形成双向relationship,意思是在AlchemyTest类中生成一个error属性,然后与AlchemyTestError中的test属性相关联
#所以实际上与上面一个relationship是一样的意思
给一对多的关系表插入数据:1
2
3
4
5test1 = session.query(AlchemyTest).filter(AlchemyTest.TestName == 'user1').first() #首先提取需要加入error的test,这个已经存在
test1.error = [AlchemyTestError(errorID='553', errorname='cuowu'),
AlchemyTestError(errorID='667', errorname='afsf')] #使用relationship()时建立的error属性来给AlchemyTestError插入数据
session.add(test1)
session.commit()stmt
使用query.join()结合两张表来查询数据表数据:1
2
3result = session.query(AlchemyTest).join(AlchemyTestError).filter(AlchemyTestError.errorname == 'cuowu').first() #查询AlchemyTest表内的数据,看哪些user有这个error
if result is not None:
print(result.TestName)
因为这两张表只有一个外键,所以query.join()知道怎么关联这两张表,但是如果没有或者不止一个外键的时候,使用其他的形式:
1 | result = session.query(AlchemyTest).join((AlchemyTestError, AlchemyTest.TestName==AlchemyTestError.TestName)).first() |
这里有一个join的reminder:
join : 如果表中有至少一个匹配,则返回行
left join : 即使右表中没有匹配,也从左表返回所有的行
right join : 即使左表中没有匹配,也从右表返回所有的行
full join : 只要其中一个表中存在匹配,就返回行
outerjoin: query.outerjoin(User.addresses) # LEFT OUTER JOIN
使用别名:
当一个table需要被call多次的时候,使用别名aliased()可以弄清:1
2name1 = aliased(AlchemyTest)
name2 = aliased(AlchemyTest)
使用subquery()来做子查询:
这个例子用于查询每个AlchemyTest的TestName对应了几个error:1
2
3
4
5stmt = session.query(AlchemyTestError.TestName, func.count('*').label('errorcount')).group_by(AlchemyTestError.TestName).subquery() #一定要使用subquery()才能使这个临时表生效
#相当于生成了一个临时表,stmt它具有表结构,这个表结构的数据我们通过"c"这个属性来获取
for user, count in session.query(AlchemyTest, stmt.c.errorcount).outerjoin(stmt, AlchemyTest.TestName==stmt.c.TestName).order_by(AlchemyTest.TestName):
#这里相当于SELECT user FROM AlchemyTest, SELECT count FROM stmt.c.errorcount LEFT OUTER JOIN stmt ON (AlchemyTest.TestName==stmt.c.TestName)
print(user.TestName, count)
使用exists():1
2
3stmt = exists().where(Address.user_id==User.id)
for name, in session.query(User.name).filter(stmt):
print(name)
一些描述关系的方法:1
2
3
4query.filter(User.addresses.contains(someaddress))
query.filter(User.addresses.any(Address.email_address == 'bar'))
query.filter(Address.user.has(name='ed'))
session.query(Address).with_parent(someuser, 'addresses')
删除数据:
删除可以直接使用session.delete()
但是与之关联的table并没有删除数据,因为SQLAlchemy并没有设定级联删除!!!
解决方案:
在一对多关系的table里的relationship设定时增加cascade:cascade="all, delete, delete-orphan”
建立多对多关系的表结构:
例子中有两个tables,分别是博客表和关键字表,一篇博客可以拥有多个关键字,一个关键字也可以对应多篇博客。
所以我们要建立一个未映射的关系表:1
2
3
4post_keywords = Table('post_keywords', Base.metadata,
... Column('post_id', ForeignKey('posts.id'), primary_key=True),
... Column('keyword_id', ForeignKey('keywords.id'), primary_key=True)
... )
这个表建立的方式与建立一个拥有映射关系的class不同。接下来创建博客表和关键字表分别与这个中间关系表用relationship()关联起来:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33>>> class BlogPost(Base):
... __tablename__ = 'posts'
...
... id = Column(Integer, primary_key=True)
... user_id = Column(Integer, ForeignKey('users.id'))
... headline = Column(String(255), nullable=False)
... body = Column(Text)
...
... # many to many BlogPost<->Keyword
... keywords = relationship('Keyword',
... secondary=post_keywords,
... back_populates='posts')
...
... def __init__(self, headline, body, author):
... self.author = author
... self.headline = headline
... self.body = body
...
... def __repr__(self):
... return "BlogPost(%r, %r, %r)" % (self.headline, self.body, self.author)
>>> class Keyword(Base):
... __tablename__ = 'keywords'
...
... id = Column(Integer, primary_key=True)
... keyword = Column(String(50), nullable=False, unique=True)
... posts = relationship('BlogPost',
... secondary=post_keywords,
... back_populates='keywords')
...
... def __init__(self, keyword):
... self.keyword = keyword
官网:https://www.sqlalchemy.org/
Python SQLAlchemy Cheatsheet : https://www.pythonsheets.com/notes/python-sqlalchemy.html
官方文档:https://docs.sqlalchemy.org/en/latest/orm/tutorial.html
首先 import sqlalchemy
可以这样检查版本 sqlalchemy.__version__
开发人员常用的关系数据库有MySQL,Oracle, SQL Server, SQLite和PostgreSQL,操作数据库的方法大致有以下2种:
常用的ORM框架模块有:SQLObject,stom,Django的ORM,peewee和SQLAlchemy。
SQLAlchemy 是 python 语言中一个比较有名的 ORM 框架。用于连接、操作数据库。提供SQL工具包以及对象-关系映射工具,使用MIT许可证发行。
1、优点:
2、缺点:
3、适用范围:适用于快速开发和团队合作开发,不适用于有大数据量(千万/亿级别)、大运算量、复杂查询的系统。
1、首先安装需要的模块:1
2
3pip install SQLAlchemy
# 如mysql数据库需要长pymysql模块
pip install pymysql
2、主流数据库的连接方式:
| 数据库 | 连接字符串 |
|---|---|
| Microsoft SQL Server | mssql+pymssql://username:password@ip:port/dbname |
| MySQL | mysql+pymysql://username:password@ip:port/dbname |
| Oracle | cx_Oracle://username:password@ip:port/dbname |
| PostgreSQL | postgressql://username:password@ip:port/dbname |
| SQLite | sqlite://file_path |
连接数据库实例3个步骤:
1. 创建engine 2. sessionmaker绑定engine 3. 创建session实例
create_engin的参数及session的创建如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 已连接mysql为例
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine(
# 'postgresql+psycopg2://{}:{}@{}:{}/{}'.format( 连接postgresql
'mysql+pymysql://{}:{}@{}:{}/{}'.format( # 连接mysql
POSTGRESQL_USER_NAME,
POSTGRESQL_PASSWORD,
POSTGRESQL_HOST,
POSTGRESQL_PORT,
POSTGRESQL_DB_NAME
),
echo=Fase, # -- 如果为真,引擎将记录所有语句 用于调试
echo_pool=False, # -- 如果为true,则连接池将记录信息输出,例如连接失效以及连接回收到默认日志处理程序,用于调试
encoding='utf-8', # 默认为 utf-8 . 这是sqlAlchemy用于在sqlAlchemy中发生的字符串编码/解码操作的字符串编码
pool_size=5, #-- 设置连接数,默认设置5个连接数,设置为0表示没有限制
max_overflow=10, # -- 允许在连接池中“溢出”的连接数,即可以在池大小设置(默认为5)之上或之外打开的连接数,默认连接数为10。
pool_timeout=30, # -- 连接超时时间,默认为30秒,超过时间的连接都会连接失败。即在放弃从池中获取连接之前等待的秒数
isolation_level="AUTOCOMMIT" # 设置引擎范围内的事务隔离级别隔离
pool_recycle=-1 # 连接重置周期,默认为-1,推荐设置7200,即如果连接数已空闲7200秒,就自动重新获取,以防止连接被关闭。
)
Session = sessionmaker(bind=engine)
session = Session()
#可以把 sessionmaker 想象成一个手机,engine 当做数据库的号码,拨通这个“号码”我们就创建了一个 Session 类。
置引擎范围内的事务隔离级别隔离:1
create_engine(isolation_level="READ_COMMITTED") # 事务隔离级别 对engine范围设置
可选值如下:
| 值 | ||
|---|---|---|
| SERIALIZABLE | 串行读 | 完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞 |
| REPEATABLE_READ | 可重复读 | 确保同一事务的多个实例在并发读取数据时,会看到同样的数据行,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读 MySQL默认隔离级别; |
| READ_COMMITTED | 提交读 | 只能读取到已经提交的数据。大部分数据库系统的默认隔离级别都是READ-COMMITED,但MySQL不是; |
| READ_UNCOMMITTED | 未提交读 | 事务中的修改,即使没有提交,对其他事务也是可见的,因此可能读到脏数据(脏读,dirty read); |
| AUTOCOMMIT | 自动提交 | 在命令行执行sql语句,每执行一次操作实质上就是一次事务 |
1、autocommit
autocommit参数表示是否自动提交事务,默认关闭,即默认sqlalchemy为每个请求(包含select操作)开启事务,但不会自动提交这个事务,需要手动提交事务。
如果autocommit=True,sqlalchemy会为每个请求(包含select操作)开启事务,并且自动提交这个事务。当你需要保证多条命令是原则性操作,则需使用
session.begin()开启事务
1 | sqlalchemy简单工作流程: |
相同点:最终效果相同(都会在执行select语句后自动提交)
不同点: sessionmaker(autocommit=True) 效果:会在执行命令完毕后断开连接,并将此连接roolback回滚放回连接池。(官方不建议使用)
isolation_level=”AUTOCOMMIT”效果:在执行命令之前不会向数据库发送begin命令。
因此两者都可以达到自动提交的效果,但实现方法完全不同。
2、autoflush
autoflush 为 True 时(默认是 True),session 进行查询之前会自动把当前累计的修改发送到数据库(注意:autoflush 并不是说在 session.add 之后会自动 flush),举个例子:1
2
3
4
5
6
7
8
9
10# 创建了一个对象,这时,这个对象几乎没有任何意义,session 不知道它的存在
>>> user = User(name='cosven')
# session.add 这个对象之后,它被 session 放到它的对象池里面去了,但这时不会发送任何 SQL 语句给数据库,数据库目前仍然不知道它的存在
>>> session.add(user)
# session1.Query 执行之前,由于 autoflush 是 True,session 会先执行 session.flush()(session.flush 的意义:session将变积累的 SQL 语句发送给数据库。),然后再发送查询语句
# 所以,这个查询是能查到 user
>>> session1.query(User).filter_by(name='cosven').first()
<__main__.User object at 0x1108f04e0>
如果 session 的 autoflush 为 False 的话,session 进行查询之前不会把当前累计的修改发送到数据库,而直接发送查询语句,所以下面这个查询是查不到对象的。1
2>>> session.add(User(name='haha'))
>>> session.query(User).filter_by(name='haha').first() # None
autoflush 的意义:session 在进行查询之前,自动的进行一次 flush 操作。
3、expire_on_commit
如果为True,在commit之后所以实例将完全过期,以便在完成事务之后,获取属性/对象都将从最近的数据库状态加载。
1 | from sqlalchemy import create_engine |
sessionmaker,我们得到一个类,一个能产生session的工厂。(每次调用都会得倒不同的session)
scoped_session类似单例模式,当我们调用使用的时候,会先在Registry里找找之前是否已经创建session了。要是有,就把这个session返回。要是没有,就创建新的session,注册到Registry中以便下次返回给调用者。这样就实现了这样一个目的:在同一个线程中,call scoped_session 的时候,返回的是同一个对象
1 | # coding =utf-8 |
| 类型名 | python中类型 | 说明 |
|---|---|---|
| Integer | int | 普通整数,一般是32位 |
| SmallInteger | int | 取值范围小的整数,一般是16位 |
| BigInteger | int或long | 不限制精度的整数 |
| Float | float | 浮点数 |
| Numeric | decimal.Decimal | 普通整数,一般是32位 |
| Varchar | str | 变长字符串 |
| Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
| Unicode | unicode | 变长Unicode字符串 |
| UnicodeText | unicode | 变长Unicode字符串,对较长或不限长度的字符串做了优化 |
| Boolean | bool | 布尔值 |
| Date | datetime.date | 时间 |
| Time | datetime.datetime | 日期和时间 |
| LargeBinary | str | 二进制文件 |
** 常用的SQLAlchemy列选项
| 选项名 | 说明 |
|---|---|
| primary_key | 如果为True,代表表的主键 |
| unique | 如果为True,代表这列不允许出现重复的值 |
| index | 如果为True,为这列创建索引,提高查询效率 |
| nullable | 如果为True,允许有空值,如果为False,不允许有空值 |
| default | 为这列定义默认值 |
注意:
orm结构中可以只写部分字段,未写出的列会将其忽略
1、使用query查询表的内容:返回的结果是一个tuple1
2
3
4
5
6
7
8
9
10
11session = Session_class()
for row in session.query(AlchemyTest).all():
print(row.TestName, row.TestNumber)
# 可以使用label()对单独的一列进行命名,这样就对name这一列命名为name_label
for row in session.query(User.name.label('name_label')).all()
pass
# 也可以用python的方法限定哪几行:
for u in session.query(User).order_by(User.id)[1:3]
pass
filter_by()可以直接使用关键字进行限制条件,但是filter()能处理更复杂的限制条件。
如果有两个限制条件是AND关系,可以直接使用两次filter()处理:1
session.query(User).filter(User.name=='ed').filter(User.fullname=='Ed Jones')
2、下面列表也展示了其他方法:(filter operator :)
| 作用 | 符号 |
|---|---|
| 相等 | == |
| 不相等 | != |
| 通配符搜索 | like(’%关键字%’) |
| 通配符搜索(不敏感) | ilike() |
| 存在于 | .in_([‘ed’, ‘wendy’, ‘jack’]) |
| 不存在于 | ~User.name.in_([‘ed’, ‘wendy’, ‘jack’]) |
| 为空 | == None |
| and | .filter(User.name == ‘ed’, User.fullname == ‘Ed Jones’) |
| or | or_(User.name == ‘ed’, User.name == ‘wendy’) |
| MATCH | .match(‘wendy’) |
3、检索返回的列表,以及列表的标量 :
| 符号 | 作用 |
|---|---|
| all() | 返回所有 |
| first() | 返回第一行 |
| one() | 检查是不是只有一行结果 |
| one_or_none() | 检查是不是一行或者没有结果 |
| scalar() | invokes the one() method, and upon success returns the first column of the row |
4、直接使用textual SQL语句 :
使用text()可以在query中使用literal strings:1
session.query(User).filter(text("id<224")).order_by(text("id")).all()
如果要直接使用完整的整条sql,可以使用text()传给from_statement():1
session.query(User).from_statement(text("SELECT * FROM users where name=:name")).params(name='ed').all()
5、计数:
可以直接使用 .count()计算有多少行:1
session.query(User).filter(User.name.like('%ed')).count()
当需要将指定的东西进行计数,就使用func.count():1
session.query(func.count(User.id)).scalar()
filter 与 filter_by 区别
filter 可以像 sql 的 where 语句一样使用 > < 等条件。引用列名时,需要通过 类名.属性名 的方式。
filter_by 使用 python 的正常参数传递方法,指定列名时,不需要额外指定类名。
1、查询
1 | # 查询ParseHtmlItem.__tablename__ 表中全部数据 |
2、增加
1 | item = ParseHtmlItem( |
3、修改
1 | # 查询要修改的数据 |
4、删除
1 | # 查询要删除的数据 |
在SQLAlchemy中每个事务对应一条或多条SQL语句,这些SQL语句需要经历如下步骤:
将修改写入磁盘
flush 操作会执行1,2步骤。
commit操作执行1,2,3步骤。
因此,flush之后你可以在当前Session中看到效果,而commit之后你才能从其它Session中看到效果。
1 | flush 使用场景为:现在已经执行一些操作,但不想结束此事务。 |
数据库操作可能因为数据类型/长度,网络原因等问题导致写入数据出错,因此要做好错误拦截避免程序关闭
1 | try: |
注意:
使用select语句推荐使用错误拦截,并使用session.rollback()回滚事务(select查询时可能数据库因为一些原因导致此次查询错误,在下次查询时可能持续报错无法正常查询)
1 |
|
session创建和管理对数据库的连接,当调用close的时候,注意,sqlalchemy不会关闭与mysql的连接,而是把连接返回到连接池。
推荐
当前session commit之后就执行close操作(原因:1.每次使用session时都会从连接池中取出,因此可以将session关闭主动放回连接池 2. 可以确保 transaction 有非常清晰的开始和结束,保持 transaction 简短,也就意味着让 transaction 能在一系列操作之后终止,而不是一直开放着。(保留session的生命周期(通常是transaction)独立))
注意:
未commit的transactions会被回滚
1 | from sqlalchemy import create_engine |
sqlalchemy 连接 数据库,select操作未commit提交(autocommit=False)这导致 pg 中产生大量的 “idle in transaction” 的长连接。导致需要 ACCESS EXCLUSIVE 锁的语句(如add column)阻塞,并阻塞所有后续需要 ACCESS SHARE 锁的读请求,导致程序异常。
session1 开启事务,并且查询test表:(autocommit=False时所有命令都会开启事务包括select语句)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
1 |
|
session2 , 修改表结构,增加字段,这时候会卡住
1 | mysql> alter table test1 add page2 int; |
session3 再开一个终端,session3模拟其他用户的请求 , 请求也会被卡住
1 | mysql> select * from test1 where id=1; |
查看processlist;
1 | mysql> show processlist; |
id=9的线程,也就是alter表那个线程,在等待锁,此时已经锁住了test表,其他的线程也不能获取锁读取test表。
1 | import pymysql |
案例:把控制台输入的数据,写入MySQL数据库1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import pymysql
def main():
no = int(input('编号: '))
name = input('名字: ')
loc = input('所在地: ')
# 1. 创建数据库连接对象
con = pymysql.connect(host='localhost', port=3306,
database='test', charset='utf8',
user='root', password='123456')
try:
# 2. 通过连接对象获取游标
with con.cursor() as cursor:
# 3. 通过游标执行SQL并获得执行结果
result = cursor.execute(
'insert into tb_dept values (%s, %s, %s)',
(no, name, loc)
)
if result == 1:
print('添加成功!')
# 4. 操作成功提交事务
con.commit()
finally:
# 5. 关闭连接释放资源
con.close()
if __name__ == '__main__':
main()
1 | #coding=utf-8 |
1 | import pymysql |
第一步:打开数据库连接
1 | import pymysql |
第二步:创建游标
cursor = db.cursor()
第三步:操作数据库
1、创建表1
2
3
4
5
6
7
8
9
10
11
12# 如果数据表已经存在使用execute()方法删除表。
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
# 创建数据表SQL语句
sql = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )"""
cursor.execute(sql)
2、查询数据#
Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。
fetchone(): 该收全部的返回结果行.
rowcount: 这是方法获取下一个查询结果集。结果集是一个对象
fetchall():接一个只读属性,并返回执行execute()方法后影响的行数。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE WHERE INCOME > {}".format(1000)
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# 打印结果
print("fname={},lname={},age={},sex={},income={}".format(fname, lname, age, sex, income))
except:
print("Error: unable to fecth data")
3、添加数据1
2
3
4
5
6
7
8
9
10
11# SQL 插入语句
sql = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
try:
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
4、修改数据1
2
3
4
5
6
7
8
9# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '{}'".format('M')
try:
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
5、删除数据1
2
3
4
5
6
7
8
9# SQL 刪除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > {}".format(20)
try:
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
第四步:关闭游标,数据库连接1
2cursor.close()
db.close()
1 | """ |
UDP 协议(User Datagram Protocol 用户数据报协议)
面向无连接,传输数据之前源端和目的端不需要建立连接
发送出去的数据不一定会接收得到
传输速率快、效率高
TCP 协议(Transmission Control Protocol传输控制协议)
面向连接,传输数据之前需要建立连接
在连接过程中进行大量的数据传输
安全可靠的传输协议
传输速度慢、效率低
TCP 与 UDP 的主要区别
1.TCP是面向连接的;UDP是无连接的
2.TCP的每个连接都是点对点的,即一对一进行;UDP的连接支持一对一,一对多,多对一以及多对多
3.TCP的传输比较安全可靠;UDP的传输则不那么可靠
4.TCP的传输比较较慢,但可以保证数据的顺序;UDP的传输速度较快,但不可保证数据的顺序
5.在对系统资源的要求上:TCP占用较多的系统资源;UDP只需少量的系统资源
创建一个基于udp的网络程序,具体步骤如下:

方式1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18from socket import *
# 1. 创建udp套接字
udp_socket = socket(AF_INET, SOCK_DGRAM)
# 2. 准备接收方的地址
# '192.168.1.103'表示目的ip地址
# 8080表示目的端口
dest_addr = ('127.0.0.1', 6666) # 注意 是元组,ip是字符串,端口是数字
# 3. 从键盘获取数据
send_data = input("请输入要发送的数据:")
# 4. 发送数据到指定的电脑上的指定程序中
udp_socket.sendto(send_data.encode('gbk'), dest_addr)
# 5. 关闭套接字
udp_socket.close()
方式2:
1 | import socket |
方式3:可连续发送数据
1 | import socket |
1 | from socket import * |
常用文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15IGNORED_EXTENSIONS = [
# 图片
'mng', 'pct', 'bmp', 'gif', 'jpg', 'jpeg', 'png', 'pst', 'psp', 'tif',
'tiff', 'ai', 'drw', 'dxf', 'eps', 'ps', 'svg',
# 音频
'mp3', 'wma', 'ogg', 'wav', 'ra', 'aac', 'mid', 'au', 'aiff',
# 视频
'3gp', 'asf', 'asx', 'avi', 'mov', 'mp4', 'mpg', 'qt', 'rm', 'swf', 'wmv',
'm4a', 'm4v', 'flv',
# 办公软件
'xls', 'xlsx', 'ppt', 'pptx', 'pps', 'doc', 'docx', 'odt', 'ods', 'odg',
'odp',
# 其它
'css', 'pdf', 'exe', 'bin', 'rss', 'zip', 'rar',
]
在python,使用: open(文件名,访问模式) 函数,可以打开一个已经存在的文件,或者创建一个新文件
| 访问模式 | 说明 |
|---|---|
| r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
| w | 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
| w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
os模块中的rename()可以完成对文件的重命名操作:rename(需要修改的文件名, 新的文件名)1
2import os
os.rename("test.py", "test1.py")
os模块中的remove()可以完成对文件的删除操作: remove(待删除的文件名)1
2import os
os.remove("毕业论文.txt")
1 | import os |
Python3 OS 文件/目录方法:
os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:
os.access(path, mode) :检验权限模式
os.chdir(path):改变当前工作目录
os.chflags(path, flags):设置路径的标记为数字标记。
os.chmod(path, mode):更改权限
os.chown(path, uid, gid):更改文件所有者
os.chroot(path):改变当前进程的根目录
os.close(fd):关闭文件描述符 fd
os.closerange(fd_low, fd_high):关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略
os.dup(fd):复制文件描述符 fd
os.dup2(fd, fd2):将一个文件描述符 fd 复制到另一个 fd2
os.fchdir(fd):通过文件描述符改变当前工作目录
os.fchmod(fd, mode):改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。
os.fchown(fd, uid, gid):修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。
os.fdatasync(fd):强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。
os.fdopen(fd[, mode[, bufsize]]):通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
os.fpathconf(fd, name):返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。
os.fstat(fd):返回文件描述符fd的状态,像stat()。
os.fstatvfs(fd):返回包含文件描述符fd的文件的文件系统的信息,像 statvfs()
os.fsync(fd):强制将文件描述符为fd的文件写入硬盘。
os.ftruncate(fd, length):裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。
os.getcwd():返回当前工作目录
os.getcwdu():返回一个当前工作目录的Unicode对象
os.isatty(fd):如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。
os.lchflags(path, flags):设置路径的标记为数字标记,类似 chflags(),但是没有软链接
os.lchmod(path, mode):修改连接文件权限
os.lchown(path, uid, gid):更改文件所有者,类似 chown,但是不追踪链接。
os.link(src, dst):创建硬链接,名为参数 dst,指向参数 src
os.listdir(path):返回path指定的文件夹包含的文件或文件夹的名字的列表。
os.lseek(fd, pos, how):设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效
os.lstat(path):像stat(),但是没有软链接
os.major(device):从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。
os.makedev(major, minor):以major和minor设备号组成一个原始设备号
os.makedirs(path[, mode]):递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。
os.minor(device):从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。
os.mkdir(path[, mode]):以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。
os.mkfifo(path[, mode]):创建命名管道,mode 为数字,默认为 0666 (八进制)
os.mknod(filename[, mode=0600, device]):创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。
os.open(file, flags[, mode]):打开一个文件,并且设置需要的打开选项,mode参数是可选的
os.openpty():打开一个新的伪终端对。返回 pty 和 tty的文件描述符。
os.pathconf(path, name):返回相关文件的系统配置信息。
os.pipe():创建一个管道. 返回一对文件描述符(r, w) 分别为读和写
os.popen(command[, mode[, bufsize]]):从一个 command 打开一个管道
os.read(fd, n):从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
os.readlink(path):返回软链接所指向的文件
os.remove(path):删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir():删除一个 directory。
os.removedirs(path):递归删除目录。
os.rename(src, dst):重命名文件或目录,从 src 到 dst
os.renames(old, new):递归地对目录进行更名,也可以对文件进行更名。
os.rmdir(path):删除path指定的空目录,如果目录非空,则抛出一个OSError异常。
os.stat(path):获取path指定的路径的信息,功能等同于C API中的stat()系统调用。
os.stat_float_times([newvalue]):决定stat_result是否以float对象显示时间戳
os.statvfs(path):获取指定路径的文件系统统计信息
os.symlink(src, dst):创建一个软链接
os.tcgetpgrp(fd):返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组
os.tcsetpgrp(fd, pg):设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。
os.tempnam([dir[, prefix]]):返回唯一的路径名用于创建临时文件。
os.tmpfile():返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。
os.tmpnam():为创建一个临时文件返回一个唯一的路径
os.ttyname(fd):返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。
os.unlink(path):删除文件路径
os.utime(path, times):返回指定的path文件的访问和修改的时间。
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]):输出在文件夹中的文件名通过在树中游走,向上或者向下。
os.write(fd, str):写入字符串到文件描述符 fd中. 返回实际写入的字符串长度
1、用python处理文本数据,并删除处理之后的数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 根据条件把一个文本分成两个文本
# with open(r'list_object.txt', 'r') as file:
# lines = file.readlines()
# for key_word in lines:
# if key_word.startswith('files/cninfo_category_daily_update/'):
# with open(r'zs_stock.txt', 'a', encoding='utf-8') as file:
# file.write(key_word)
# else:
# with open(r'zs_bond.txt', 'a', encoding='utf-8') as file:
# file.write(key_word)
# 处理文本数据,并删除处理之后的数据
kafka_list = []
with open(r'files/zs_stock.txt', encoding='utf-8') as file:
lines = file.readlines()
print('读取文本行数:', len(lines))
for num in lines[0:5]:
kafka_list.append(num)
lines.remove(num)
print('kafka_list:', kafka_list)
with open(r'files/zs_stock.txt', 'w', encoding='utf-8') as f:
print('删除已传送jds路径之后文本行数:', len(lines))
for i in lines:
f.write(i)
2、输入文件的名字,然后程序自动完成对文件进行备份1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# coding=utf-8
oldFileName = input("请输入要拷贝的文件名字:")
with open(oldFileName, 'r', encoding='utf-8') as oldFile:
# 如果打开文件
if oldFile:
# 提取文件的后缀
fileFlagNum = oldFileName.rfind('.')
if fileFlagNum > 0:
fileFlag = oldFileName[fileFlagNum:]
# 组织新的文件名字
newFileName = oldFileName[:fileFlagNum] + '[复件]' + fileFlag
# 创建新文件
with open(newFileName, 'w', encoding='utf-8') as newFile:
# 把旧文件中的数据,一行一行的进行复制到新文件中
for lineContent in oldFile.readlines():
newFile.write(lineContent)
3、批量在文件名前加前缀
1 | # coding=utf-8 |
操作系统会为每一个进程分配独立的内存空间,的那这样会占用独立的资源,对系统的开销较大。一般情况下我们可以使用多线程来完成多任务的开发,一个进程中包含了多个线程,对系统的开销较小一个进程中至少有一个线程,默认的这个线程我们叫做主线程。
单线程模拟人脑:
1 | import time |
多线程:
1 | import threading |
========================================
(wiki陶喵)
在并发程序中,一个重要的需要注意的点是程序的可重入性 https://blog.csdn.net/vincent040/article/details/50978979
以下以一个例子来介绍。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38# encoding : utf-8
from flask import Flask
import threading
lock = threading.Lock()
app = Flask(__name__)
class my_model():
def __init__(self):
self.weights = 1
self.mid_data = 0
def predict(self,input_data):
self.mid_data = 0
for i in range(1000):
i+1
for i in range(1000000):
self.mid_data += (self.weights + input_data)
for i in range(1000):
i+1
result = self.mid_data
return result
m = my_model()
@app.route("/zero",methods=["GET"])
def zero():
res = m.predict(0)
return str(res)
@app.route("/one",methods=["GET"])
def one():
res = m.predict(1)
return str(res)
if __name__=="__main__":
app.run( host = "0.0.0.0", port = 9865 )
如上,这个程序看似没有什么问题。在连续访问下,能得到正确结果,但是当出现高并发的访问的时候,程序的结果就不可预知了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22(torch36) zhujinyi@gpuserver010:/data/nfs/wrk-4.1.0$ wrk -t 4 -c 128 -d 60s -s test_m2.lua http://localhost:9865/one
Running 1m test @ http://localhost:9865/one
4 threads and 128 connections
953822
3185088
2847474
2940568
713724
3103776
2987122
3380356
105864
3818912
148244
1301280
1555600
1495616
4196668
686306
4317080
729890
909054
这种情况下,常用的解决办法是加锁保护共享数据,界定临界区。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40# encoding : utf-8
from flask import Flask
import threading
lock = threading.Lock()
app = Flask(__name__)
class my_model():
def __init__(self):
self.weights = 1
self.mid_data = 0
def predict(self,input_data):
lock.acquire()
self.mid_data = 0
for i in range(1000):
i+1
for i in range(1000000):
self.mid_data += (self.weights + input_data)
for i in range(1000):
i+1
result = self.mid_data
lock.release()
return result
m = my_model()
@app.route("/zero",methods=["GET"])
def zero():
res = m.predict(0)
return str(res)
@app.route("/one",methods=["GET"])
def one():
res = m.predict(1)
return str(res)
if __name__=="__main__":
app.run( host = "0.0.0.0", port = 9865 )
这样可以得到正确的结果。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19(torch36) zhujinyi@gpuserver010:/data/nfs/wrk-4.1.0$ wrk -t 4 -c 128 -d 60s -s test_m2.lua http://localhost:9865/one
Running 1m test @ http://localhost:9865/one
4 threads and 128 connections
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
2000000
当然,大粒度的锁会严重影响程序的性能,不推荐把锁加到函数级别,另一种可以得到正确结果的方案是用更多的空间。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class my_model():
def __init__(self):
self.weights = 1
self.mid_data = 0
def predict(self,input_data):
tmp_data = 0
for i in range(1000):
i+1
for i in range(1000000):
tmp_data += (self.weights + input_data)
for i in range(1000):
i+1
result = tmp_data
return result
这样写也可以得到正确结果。
1 | import time |
1 | import re |
1 |
|
执行结果如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<_sre.SRE_Match object; span=(0, 12), match='hello world!'>
@@@@@@@@m.string: hello world!
m.re: re.compile('(\\w+) (\\w+)(?P<sign>.*)')
m.pos: 0
m.endpos: 12
m.lastindex: 3
m.lastgroup: sign
m.group(1,2): ('hello', 'world')
m.groups(): ('hello', 'world', '!')
m.groupdict(): {'sign': '!'}
m.start(2): 6
m.end(2): 11
m.span(2): (6, 11)
m.expand(r'\2 \1\3'): world hello!
--------p.pattern: (\w+) (\w+)(?P<sign>.*)
p.flags: 48
p.groups: 3
p.groupindex: {'sign': 3}
smarter
%%%%%%%%%%replacedStr= crifanli
正则表达式之数字:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
正则表达式在线生成工具: https://www.w3cschool.cn/tools/index?name=create_reg
1 | 一、校验数字的表达式 |
datetime是Python处理日期和时间的标准库。
datetime表示的时间需要时区信息才能确定一个特定的时间,否则只能视为本地时间。
如果要存储datetime,最佳方法是将其转换为timestamp再存储,因为timestamp的值与时区完全无关。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from datetime import datetime, timedelta, timezone
# 1. 获取当前日期和时间和指定日期和时间
now = datetime.now() # 获取当前datetime
print(now, type(now))
dt = datetime(2019, 4, 19, 12, 20) # 用指定日期时间创建datetime
print(dt)
# 2. datetime转换为timestamp
dt_stamp = dt.timestamp()
print(dt_stamp)
# timestamp转换为datetime
print(datetime.fromtimestamp(dt_stamp))
print(datetime.utcfromtimestamp(dt_stamp)) # UTC时间
# 3. str转换为datetime
cday = datetime.strptime('2019-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
print(cday)
# datetime转换为str
print(now.strftime('%a, %b %d %H:%M'))
# 4. datetime加减
ten_hour = now + timedelta(hours=2)
print(ten_hour)
print(now - timedelta(days=1))
print(now + timedelta(days=2, hours=12))
# 5. 本地时间转换为UTC时间
# 北京时间是UTC+8:00时区的时间,而UTC时间指UTC+0:00时区的时间
tz_utc_8 = timezone(timedelta(hours=8)) # 创建时区UTC+8:00
dt = now.replace(tzinfo=tz_utc_8) # 强制设置为UTC+8:00
print(dt)
# 6. 时区转换
# 可以先通过utcnow()拿到当前的UTC时间,再转换为任意时区的时间:
utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
print(utc_dt)
# astimezone()将转换时区为北京时间:
bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
print(bj_dt)
1 | import datetime |
假设你获取了用户输入的日期和时间如2015-1-21 9:01:30,以及一个时区信息如UTC+5:00,均是str,请编写一个函数将其转换为timestamp:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import re
from datetime import datetime, timezone, timedelta
def to_timestamp(dt_str, tz_str):
t = datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
tz = re.match(r'\w{3}([\+\-]\d{1,2})\:\d{2}', tz_str).group(1)
tz = int(tz)
t_utc = t.replace(tzinfo=timezone(timedelta(hours=tz)))
print(t_utc.timestamp())
return t_utc.timestamp()
t1 = to_timestamp('2015-6-1 08:10:30', 'UTC+7:00')
assert t1 == 1433121030.0, t1
t2 = to_timestamp('2015-5-31 16:10:30', 'UTC-09:00')
assert t2 == 1433121030.0, t2
print('ok')
==========================
案例1:打印昨天的时间:1
2
3
4
5
6
7
8
9
10
11# 引入 datetime 模块
import datetime
def getYesterday():
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
yesterday = today - oneday
return yesterday
# 输出
print(getYesterday()) # 2019-07-22
案例2:格式化时间1
2
3
4
5
6
7
8
9
10import time
# 格式化成2019-07-23 11:45:39形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
# 格式化成Sat Mar 28 22:24:24 2016形式
print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))
# 将格式字符串转换为时间戳
a = "Sat Mar 28 22:24:24 2019"
print(time.mktime(time.strptime(a, "%a %b %d %H:%M:%S %Y")))
执行结果如下图:
案例3:输出某月的日历
1 | import calendar |
执行结果如下图:
案例4:将字符串的时间转换为时间戳
1 | import time |
执行结果如下图:
案例5:获取几天前的时间
1 | import time |
执行结果如下图:
案例6:将时间戳转换为指定日期
1 | import time |
执行结果如下图:
1 | import datetime |
执行结果如下图:
指定时间戳:
1 | import time |
1 | import datetime |
模块(Module):是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。
如果一个文件中有all变量,那么也就意味着这个变量中的元素,不会被from xxx import *时导入
模块让你能够有逻辑地组织你的 Python 代码段。
把相关的代码分配到一个模块里能让你的代码更好用,更易懂。
模块能定义函数,类和变量,模块里也能包含可执行的代码。
包括:内置模块,自定义模块,第三方模块;
import 导入文件都做了哪些事?
以源文件为准产生一个名称空间
以刚刚产生的名称空间为准,执行源文件的代码
会在当前文件中定义一个名字,这个名字就是模块名,用来引用模块中的名字
模块的搜索路径:模块的查找顺序是:内存中已经加载的模块->内置模块(系统内置那些)->sys.path路径中包含的模块
1.安装的方式
找到模块的压缩包
解压
进入文件夹
执行命令: python setup.py install
注意:
如果在install的时候,执行目录安装,可以使用:python setup.py install --prefix=安装路径
2.模块的引入
在程序中,使用from import 即可完成对安装的模块使用
from 模块名 import 模块名或者*
包:包就是一个包含有init.py文件的文件夹。包的导入和导入模块类似,形式:import 包名,只不过想要使用包中的工具,则需要在包的 init 文件下导入此包的模块。
__init__.py控制着包的导入行为
init 的作用:将此包下的模块进行导入,在其他地方调用这个包时,以便访问使用这个包的方法。
安装python模块已存在,可以指定安装的目录进行安装:1
pip install --target=d:\program\python\python37\lib\site-packages\twisted _win32stdio
面向对象(object-oriented ;简称: OO) 至今还没有统一的概念 我这里把它定义为: 按人们 认识客观世界的系统思维方式,采用基于对象(实体) 的概念建立模型,模拟客观世界分析、设 计、实现软件的办法。
面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。 这种方法把软件系统中相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。
类(Class): 是一对相同特征或行为的事物的一个统称,是抽象的,不能直接使用它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
属性:对象具有的特征(有什么),用来描述数据;
方法:对象具有的行为(能做什么),用来描述数据相关的操作;
作用:类相当于制造飞机的图纸,是一个模板,是负责创建对象的,它来进行创建的飞机就相当于对象;
类的抽象:拥有相同(或者类似)属性和行为的对象都可以抽像出一个类
对象:是由类创建出来的一个具体存在,可以直接使用。一个类创建出来的对象
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
案例:面向对象_扑克牌发牌程序 (Python经典编程案例)
接口:
1 | # coding=utf-8 |
对象:
init方法
“魔法”方法
self
所谓的self,可以理解为自己
可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思
某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可
保护对象属性:
如果有一个对象,当需要对其进行修改属性时,有2种方法:
为了更好的保存属性安全,即不能随意修改,一般的处理方式为:
Python中没有像C++中public和private这些关键字来区别公有属性和私有属性
它是以属性命名方式来区分,如果在属性名前面加了2个下划线’__’,则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。
__del__()方法
创建对象后,python解释器默认调用init()方法;
当删除一个对象时,python解释器也会默认调用一个方法,这个方法为del()方法
继承
子类在继承的时候,在定义类时,小括号()中为父类的名字
父类的属性、方法,会被继承给子类
多态
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
new和init的作用
new至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
new必须要有返回值,返回实例化出来的实例,这点在自己实现new时要特别注意,可以return父类new出来的实例,或者直接是object的new出来的实例
init有一个参数self,就是这个new返回的实例,init在new的基础上可以完成一些其它初始化的动作,init不需要返回值
我们可以将类比作制造商,new方法就是前期的原材料购买环节,init方法就是在有原材料的基础上,加工,初始化商品环节
try语句处理异常,是这样做的:
首选,try子语句(try和except关键字之间的语句)会被执行。
如果没有异常发生,except 子句被略过。
如果有异常发生,try后面的其他语句就被跳过了,如果异常类型在except关键字后匹配,这个except子句被执行。
如果没有异常发生,else子句就会被执行。else的作用是它避免了捕获未保护的代码所发起的异常。
finally子语会在try子句执行完毕之前执行,不管是否发生或者不发生异常。当一个异常发生在try子句中却未被处理时(或者发生在except或者else子句中时),finally子句执行完后会再次抛出异常。
1 | import random |
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
而函数式编程(请注意多了一个“式”字)——Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。
我们首先要搞明白计算机(Computer)和计算(Compute)的概念。
在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。
而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
高阶函数英文叫Higher-order function。
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 1. 变量可以指向函数
# 结论:函数本身也可以赋值给变量,即:变量可以指向函数。
print(abs(-10)) # 10
print(abs) # <built-in function abs>
f = abs
print(f) # <built-in function abs>
# 说明变量f现在已经指向了abs函数本身。直接调用abs()函数和调用变量f()完全相同。
print(f(-10)) # 10
# 2. 函数名也是变量
# 由于abs函数实际上是定义在import builtins模块中的,
# 所以要让修改abs变量的指向在其它模块也生效(修改内置函数),要用import builtins; builtins.abs = 10
# 3. 传入函数
# 既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x, y, f):
return f(x) + f(y)
print(add(-5, 6, abs))
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
1 |
|
练习:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 练习1:利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。
# 输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']:
def normalize(name):
# 第一种方式
# return name.capitalize()
# 第二种方式
# if not isinstance(name, str):
# raise TypeError('***参数不是字符串***')
# name1 = name[0].upper() # name的首字母大写(这里输出只有首字母)
# name2 = name[1:].lower() # name的除首字母以后全部小写(输出只有除首字母的部分)
# name = name1 + name2 # 所以要连起来重新赋值给name
# return name
# 第三种方式
if not isinstance(name, str):
raise TypeError('name input is not a string')
return name[0].upper() + name[1:].lower()
L1 = ['adam', 'LISA', 'barT']
L2 = list(map(normalize, L1))
print(L2)
# 练习2:Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:
from functools import reduce
def prod(L):
return reduce(lambda x, y: x*y, L)
print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
if prod([3, 5, 7, 9]) == 945:
print('测试成功!')
else:
print('测试失败!')
# 练习3:利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:
from functools import reduce
def str2float(s):
from functools import reduce # 调用reduce函数
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def char2num(s): # 定义把数字字符元素转为数字元素的函数
return DIGITS[s]
i = s.find('.') # 找到'.'所在的索引位
L1 = reduce(lambda x, y: x * 10 + y, map(char2num, s[:i])) # 取'.'之前的元素计算
L2 = reduce(lambda x, y: x / 10 + y, map(char2num, s[:i:-1])) / 10 # 取'.'之后的元素计算
return L1 + L2
print('str2float(\'123.456\') =', str2float('123.456'))
if abs(str2float('123.456') - 123.456) < 0.00001:
print('测试成功!')
else:
print('测试失败!')
Python内建的filter()函数用于过滤序列。
和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
由于filter()使用了惰性计算,所以只有在取filter()结果的时候,才会真正筛选并每次返回下一个筛出的元素。
1 | # 例如,在一个list中,删掉偶数,只保留奇数,可以这么写: |
sorted()也是一个高阶函数。用sorted()排序的关键在于实现一个映射函数。1
2
3
4
5
6
7
8
9
10
11
12
# Python内置的sorted()函数就可以对list进行排序:
print(sorted([36, 5, -12, 9, -21])) # [-21, -12, 5, 9, 36]
# sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:
print(sorted([36, 5, -12, 9, -21], key=abs)) # [5, 9, -12, -21, 36]
# 默认情况下,对字符串排序,是按照ASCII的大小比较的,由于'Z' < 'a',结果,大写字母Z会排在小写字母a的前面。
print(sorted(['bob', 'about', 'Zoo', 'Credit'])) # ['Credit', 'Zoo', 'about', 'bob']
# 忽略大小写来比较两个字符串,实际上就是先把字符串都变成大写(或者都变成小写),再比较。
print(sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)) # ['about', 'bob', 'Credit', 'Zoo']
# 要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True:
print(sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)) # ['Zoo', 'Credit', 'bob', 'about']
函数作为返回值:一个函数可以返回一个计算结果,也可以返回一个函数。返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。
返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
1 | def count(): |
Python对匿名函数的支持有限,只有一些简单的情况下可以使用匿名函数。1
2
3
4
5
6
7
8
9
10
11
# 匿名函数lambda x: x * x实际上就是:def f(x): return x * x
list1 = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(list1) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
# 同样,也可以把匿名函数作为返回值返回,比如:
def build(x, y):
return lambda: x * x + y * y
print(build(2, 3))
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。
在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。
Python的decorator可以用函数实现,也可以用类实现。decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。1
2
3
4
5
6
7
8
9
10
11
12
13
14# 本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
now()
1 | import functools |
函数:把具有独立功能的代码块组织一个小模块,在需要的时候调用
返回值:就是程序中函数完成一件事情后,最后给调用者的结果
全局变量:在函数外边定义的变量,全局变量能够在所有的函数中进行访问;如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错;如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的,小技巧强龙不压地头蛇
对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使用global时无法修改全局变量。对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global时也可修改全局变量。
浅拷贝 copy(): 不拷贝子对象的内容,只拷贝子对象的引用;
深拷贝 deepcopy(): 会连子对象的内存也全部拷贝一份,对子对象的修改不会影响原对象。
LEGB规则:python查找名称时,查找顺序:local -> enclosed -> global -> built in
Lambda函数:是一种比较小的匿名函数
规则:只允许包含一个表达式,计算结果就是函数的返回值1
2
3
4x = lambda a, b: a*b
print(x(3, 6))
y = lambda c: c*4
print(y(6))
定义时小括号中的参数,用来接收参数用的,称为 “形参”
调用时小括号中的参数,用来传递给函数用的,称为 “实参”
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。
默认参数:要牢记一点:默认参数必须指向不变对象!1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def enroll(name, gender, age=6, city='Beijing'):
"""可以把年龄和城市设为默认参数"""
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
enroll('Sarah', 'F')
# 默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
# 如果默认参数指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
# 这时可以用None这个不变对象来实现无论调用多少次,都不会有问题:
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
可变参数:1
2
3
4
5
6
7
8
9
10
11# 如计算计算a^2 + b^2 + c^2 + ……。
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
print(calc(1, 2))
# Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去
nums = [1, 2, 3]
print(calc(*nums)) # 这种写法相当有用,而且很常见。
关键字参数:至于到底传入了哪些,就需要在函数内部通过kw检查,如:if 'city' in kw:1
2
3
4
5
6
7
8
9
10
11
12
13
def person(name, age, **kw):
"""kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra"""
print('name:', name, 'age:', age, 'other:', kw)
# 在调用该函数时,可以只传入必选参数:
person('Michael', 30)
# 可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, city=extra['city'], job=extra['job'])
# 当然,上面复杂的调用可以用简化的写法:
person('Jack', 24, **extra)
命名关键字参数:是为了限制调用者可以传入的参数名,同时可以提供默认值。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。
# 缺少 *,city和job被视为位置参数
def person1(name, age, *, city, job):
print(name, age, city, job)
# 命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错
person1('Jack', 24, city='Beijing', job='Engineer')
# 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
def person2(name, age, *args, city, job):
print(name, age, args, city, job)
# 由于命名关键字参数city具有默认值,调用时,可不传入city参数:
def person3(name, age, *, city='Beijing', job):
print(name, age, city, job)
person3('Jack', 24, job='Engineer')
参数检查:1
2
3
4
5
6
7
8
9
10def my_abs(x):
# 数据类型检查可以用内置函数isinstance()实现:
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
print(my_abs(5))
递归函数:自己调用自己的函数;
包含两个部分:①终止条件;②递归步骤。
处理大数据时慎用,因为会创建大量函数对象,过量的消耗内存和运算能力。
理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
举个例子,我们来计算阶乘n! = 1 x 2 x 3 x … x n,用函数fact(n)表示,可以看出:fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n。所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。1
2
3
4
5
6def fact(n):
if n==1:
return 1
return n * fact(n - 1)
fact(5)
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000)。
解决递归调用栈溢出的方法是通过尾递归优化(通过尾递归防止栈溢出),事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。1
2
3
4
5
6
7
8
9
10
11
12
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
fact_iter(5, 1)
fact_iter(4, 5)
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。
函数高级特性:切片,迭代,生成器,迭代器
1 | L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] |
迭代:
迭代(Iteration):如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。
生成器: 如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator
generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 第一种:创建生成器的方法很简单,只要把一个列表生成式的[]改成()
L = [x * x for x in range(10)]
print(L) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
g = (x * x for x in range(10))
print(g) # <generator object <genexpr> at 0x1022546d0>
for n in g:
print(n)
# 斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
# 第二种:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
# 变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
def fib1(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 只需要把print(b)改为yield b就可以了
a, b = b, a + b
n = n + 1
return 'done'
print(fib1(6))
迭代器:
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
1 |
|
控制语句
注意:
代码的缩进格式很重要 建议4个空格来控制
根据逻辑值(True,Flase)判断程序的运行方向
Ture:表示非空的量(String,tuple元组 、list、set、dictonary),所有非零的数字,False:0,None 、空的量
逻辑表达式 可以包含 逻辑运算符 and or not
break的作用是提前结束循环;
continue的作用是提前结束本轮循环,并直接开始下一轮循环
1 |
|
Python中的循环语句有 for 和 while。
在python中,每个变量使用前都必须赋值,变量赋值之后才会被创建。
序列:一块用来存放多个值的连续内存空间。
作用:进行数据存储操作。遍历时,索引位置和对应值可以用enumerate()函数同时得到。
常用的序列结构有:字符串,列表,元组,字典,集合。
序列解包:可用于元组,列表,字典,让我们方便地对多个变量赋值,如:x, y, z = (20, 30, 10)
列表:用于存储任意数目,任意类型的数据集合,有序,元素可变。
格式:a = [12, 20, ‘abc’, True]
特点:
常用方法:
返回某项是否是列表中的元素:‘y’ in list_x
1 |
|
列表生成式:列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
d1 = [x * x for x in range(1, 11) if x % 2 == 0]
print(d1) # [4, 16, 36, 64, 100]
# 还可以使用两层循环,可以生成全排列:
d2 = [m + n for m in 'ABC' for n in 'XYZ']
print(d2) # ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
# 列出当前目录下的所有文件和目录名,可以通过一行代码实现:
import os
d3 = [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
print(d3)
# 列表生成式也可以使用两个变量来生成list:
dict = {'x': 'A', 'y': 'B', 'z': 'C'}
d4 = [k + '=' + v for k, v in dict.items()]
print(d4) # ['x=A', 'y=B', 'z=C']
# 把一个list中所有的字符串变成小写:
L = ['Hello', 'World', 'IBM', 'Apple']
d5 = [s.lower() for s in L]
print(d5) # ['hello', 'world', 'ibm', 'apple']
# 带if else
d6 = [x if x % 2 == 0 else -x for x in range(1, 11)]
print(d6) # [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
元组:与列表类似,不同之处在于元组的元素不能修改,用于存储一串信息。
特点:元组的访问和处理速度比列表快,是不可变序列。
tuple的陷阱:当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来。1
2
3
4
5
6
7
8
9
10
11
12
# 只有1个元素的tuple定义时必须加一个逗号,
t = (1,)
# 看一个“可变的”tuple:
# tuple所谓的“不变”是说,tuple的每个元素,指向永远不变,但指向的这个list本身是可变的
t = ('a', 'b', ['A', 'B'])
t[2][0] = 'X'
t[2][1] = 'Y'
# 可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素
print(t[-1])
字典:是键值对的无序可变序列,作用:可以存储多个数据,通常用于存储描述一个物体相关的信息。dict是用空间来换取时间的一种方法。
dict的key必须是不可变对象,通过key计算位置的算法称为哈希算法(Hash)。要保证hash的正确性,作为key的对象就不能变。
用in检测键是否在字典中;python3.5及以前的版本中,keys方法返回列表中的键是无序的。
特点:
方法:
1 | d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} |
遍历字典:
如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# -*- coding: utf-8 -*-
# 弃用警告:从collections中导入ABCs已被弃用,并在python3.8中将停止工作,可使用collections.abc代替它进行使用
from collections.abc import Iterable
print(isinstance('abc', Iterable)) # str是否可迭代
print(isinstance([1, 2, 3], Iterable)) # list是否可迭代
print(isinstance(123, Iterable)) # 整数是否可迭代
# 如果要对list实现类似Java那样的下标循环怎么办?
# Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:
for i, value in enumerate(['A', 'B', 'C']):
print(i, value)
# 面的for循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:
for x, y in [(1, 1), (2, 4), (3, 9)]:
print(x, y)
字典的核心底层原理:字典的核心是散列表,散列表是一个稀疏数组,数组的每个单元叫bucket;每个bucket有2个部分,一个是键对象的引用,一个是值对象的引用;所有bucket结构和大小一致,可通过偏移量来读取指定bucket。
扩容:创造更大的数组,把原有的内容拷贝到新数组中;python会根据散列表的拥挤程度扩容,接近2/3时,数组就会扩容。
特点:无序可变,元素不能重复,底层是字典的实现,集合中所有的元素都是字典的键,所以不能重复。
方法:
1 | # 要创建一个set,需要提供一个list作为输入集合: |
不可变集合:frozenset是不可变,可散列的1
2
3x = set([1, 2, 3, 1, 3, 5])
y = frozenset(x)
print(y) # frozenset({1, 2, 3, 5})
运算符:
| 运算符 | Python 表达式 | 结果 | 描述 | 支持的数据类型 |
|---|---|---|---|---|
| + | [1, 2] + [3, 4] | [1, 2, 3, 4] | 合并 | 字符串、列表、元组 |
| * | ‘Hi!’ * 4 | [‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’] | 复制 | 字符串、列表、元组 |
| in | 3 in (1, 2, 3) | True | 元素是否存在 | 字符串、列表、元组、字典 |
| not in | 4 not in (1, 2, 3) | True | 元素是否不存在 | 字符串、列表、元组、字典 |
内置函数:
cmp(item1, item2):比较两个值
len(item):计算容器中元素个数
max(item):返回容器中元素最大值
min(item):返回容器中元素最小值
del(item):删除变量
1、用列表和字典存储表信息,并打印出表中工资高于 15000 的数据1
2
3
4
5
6
7r1 = dict(name="高小一", age=18, salary=30000, city="北京")
r2 = dict(name="高小二", age=19, salary=20000, city="上海")
r3 = dict(name="高小三", age=20, salary=10000, city="深圳")
tb = [r1, r2, r3]
for x in tb:
if x.get("salary") > 15000:
print(x)
相互转换:
将数值转换成字符串,可以使用str()和repr()函数
1、判断类型:(9个)
2、查找和替换:(7个)
3、大小写转换:(5个)
4、文本对齐:(3个)
5、去除空白字符:(3个)
6、拆分和连接:(5个)
7、其它
maketrans(): 返回在translate函数中使用的转换表。
max(str): 从字符串str返回最大字母字符。
translate(table, deletechars=根据转换表STR(256个字符): 除去那些在del字符串转换字符串。
zfill(width): 返回原始字符串,左边填充为零,总共有宽度(width)字符; 对于数字zfill()保留给定的任何符号(少于一个零)。
python编码风格:PEP8(Python Enhancement Proposal)python增强提案
ython 3的字符串使用Unicode,直接支持多语言。
UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码,很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码。
如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。Python对bytes类型的数据用带b前缀的单引号或双引号表示,bytes的每个字符都只占用一个字节。为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。1
2
3
4
5
6
7
8
9
10
11
12
13
14# 以Unicode表示的str通过encode()方法可以编码为指定的bytes
'ABC'.encode('ascii')
'中文'.encode('utf-8')
# 如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法
# 如果bytes中只有一小部分无效的字节,可以传入errors='ignore'忽略错误的字节
b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
# 当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:
# 第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
# 第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
bytes:二进制
互联网上数据的都是以二进制的方式传输的
str :unicode的呈现形式
字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等
字符集(Character set)是多个字符的集合
字符集包括:ASCII字符集、GB2312字符集、GB18030字符集、Unicode字符集等
ASCII编码是1个字节,而Unicode编码通常是2个字节。
UTF-8是Unicode的实现方式之一,UTF-8是它是一种变长的编码方式,可以是1,2,3个字节
str 使用encode方法转化为 bytes
bytes通过decode转化为str
编码方式解码方式必须一样,否则就会出现乱码
第一种格式化:在字符串内部,%s表示用字符串替换,%d表示用整数替换,%f表示用浮点数替换,%x表示用十六进制替换,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。
第二种格式化:使用字符串的format()方法,它会用传入的参数依次替换字符串内的占位符{0}、{1}……,
1 | print('{1} and {0}'.format('spam', 'eggs')) # eggs and spam |
关键字:即保留字,在python中已经使用的标识符,具有特殊的功能和含义。
1 | # 查看关键字 |
chr(),把数字转换为字母,如chr(98) # 输出:b。(把编码转换为对应的字符)ord(),刚好与chr()相反,把字母转换为数字。(获取字符的整数表示)dir(),可以快速的查看指定类或者模块包含的全部内容(包括函数,方法,类,变量等),如查看列表的方法:dir(list)。unichr(x ):将一个整数转换为Unicode字符
str(x ):将对象 x 转换为字符串
repr(x ):将对象 x 转换为表达式字符串
int(x [,base ]):将x转换为一个整数
long(x [,base ]):将x转换为一个长整数
float(x ):将x转换到一个浮点数
complex(real [,imag ]):创建一个复数
hex(x ):将一个整数转换为一个十六进制字符串
oct(x ):将一个整数转换为一个八进制字符串
id():在python中,值是靠引用来传递来的。我们可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标示。
Python的内置函数
1 | def myfilter(mystr): |
内置函数应用:
1.使用chr()与ord()可以实现随机的验证码1
2
3
4
5
6import random
li = []
for i in range(6):
r = random.randrange(65, 91)
li.append(chr(r))
print(''.join(li))
2.过滤出列表中大于2的值1
2
3
4
5
6li=[1,2,3,4,5,6,7,8,9,10]
def f1(a):
if a>2:
return True
res=filter(f1,li)
print(list(res))
结合匿名函数lambda函数后,实现的过程更加简单1
2
3li=[1,2,3,4,5,6,7,8,9,10]
res=filter(lambda a:a>2,li)
print(list(res))
3.有列表[0,1,2,3,4,5,6,7,8,9],都加101
2
3
4
5
6
7
8li=[1,2,3,4,5,6,7,8,9]
def f1():
result=[]
for i in li:
result.append(i+10)
return result
print(f1())
使用map函数,实现的代码为:1
2
3
4
5
6li=[1,2,3,4,5,6,7,8,9]
def f1(a):
return a+10
result=map(f1,li)
print(list(result))
结合lambda函数,实现的代码更加精简1
2
3li=[1,2,3,4,5,6,7,8,9]
result=map(lambda a:a+10,li)
print(list(result))
1 | #coding=utf-8 |
变量:是数据在内存中分配的空间,程序用来处理数据,而变量用来存储数据。
引用:在python中,变量也称为引用,因为变量存储的就是对象的地址,变量通过地址引用了对象,变量位于栈内存,对象位于堆内存。
常量:所谓常量就是不能变的变量
1 |
|
%s:字符串;
%d:有符号10进制数,%06d表示整数位数,不足以0补全;
%f:浮点数,%02f,小数点后显示2位;
1 | # %03d 表示有3个整数位数,如不足以0补全,比如:132,087,006,得保证有3位数 |
数字型:
整型(int)
浮点型(float):如3.14,可表:314E-2或314e-2
布尔型(bool)Tre非零数(非0即真)
复数型( comples)
非数字型
字符串 (string)
列表 (list)
元组 (Tuple)
字典 (Dictionary)
集 (Sets)
可以使用type(变量的名字),来查看变量的类型。
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
标识符:自己可以起名字的地方,包括变量,方法,函数,类,模块;
1.可以由大小写字母,数字,下划线(_)组成,其中数字不能开头;
2.标识符不能是python关键字,但可以包含关键字;
3.标识符不能包含空格。
对象本质:一个内存模块,拥有特定的值,支持特定类型的相关操作;
引用:在python中,变量也称为引用,因为变量存储的对象就是地址。
基本语法 :
在Python中严格区分大小写;
Python中的每一行就是一条语句,每条语句以换行结束;
Python中每一行语句不要过长(规范中建议每行不要超过80个字符); “rulers”:[80],
一条语句可以分多行编写,多行编写时语句后边以\结尾 ;
Python是缩进严格的语言,所以在Python中不要随便写缩进 ;
在Python中使用#来表示注释,#后的内容都属于注释,注释的内容将会被解释器所忽略;一般习惯上#后边会跟着一个空格
IDE(Integrated Development Environment),集成开发环境。是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。
常用IDE : Atom、Sublime、Pycharm、VS Code是Python使用者常用的几款IDE。pycharm-professional-2018.1.3 : 第三方IDE打开多个.py文件时,页面较为友好。同时还有以下优点:智能提示、代码着色、代码跳转、自动完成、单元测试、版本控制等等。
| 运算符 | 描述 |
|---|---|
[] [:] |
下标,切片 |
** |
指数 |
~ + - |
按位取反, 正负号 |
* / % // |
乘,除,模,整除 |
+ - |
加,减 |
>> << |
右移,左移 |
& |
按位与 |
^ |
按位异或 |
<= < > >= |
小于等于,小于,大于,大于等于 |
== != |
等于,不等于 |
is is not |
身份运算符 |
in not in |
成员运算符 |
not or and |
逻辑运算符 |
= += -= *= /= %= //= **= &= ^= >>= <<= |
(复合)赋值运算符 |
1 | 1. print() |
用任何编程语言来开发程序,都是为了让计算机干活,比如下载一个MP3,编写一个文档等等,而计算机干活的CPU只认识机器指令,所以,尽管不同的编程语言差异极大,最后都得“翻译”成CPU可以执行的机器指令。而不同的编程语言,干同一个活,编写的代码量,差距也很大。
比如,完成同一个任务,C语言要写1000行代码,Java只需要写100行,而Python可能只要20行;C程序运行1秒钟,Java程序可能需要2秒,而Python程序可能就需要10秒
Java占据了世界上绝大部分电商,金融,通信等服务端应用的开发;
而C,C++占据了世界上大部分贴近操作系统的硬件编程;
编译型语言:c,c++,Go,Swift,Object-c,Pascal
解释型语言:JavaScript,Python,Rby,PHP,Perl,Erlang
混合型:Java,C#
是一种解释型,面向对象的语言;
由吉多·范罗苏姆(Guido van Rossum)于1989年发明,1991年正式公布;
官网 www.python.org;
设计哲学:优雅,明确,简单。
许多大型网站就是用Python开发的,例如YouTube、Instagram,还有国内的豆瓣。很多大公司,包括Google、Yahoo等,甚至NASA(美国航空航天局)都大量地使用Python。
1. 1989年圣诞节:Guido von Rossum开始写Python语言的编译器。
2. 1991年2月:第一个Python编译器(同时也是解释器)诞生,它是用C语言实现的(后面),可以调用C语言的库函数。在最早的版本中,Python已经提供了对“类”,“函数”,“异常处理”等构造块的支持,还有对列表、字典等核心数据类型,同时支持以模块为基础来构造应用程序。
3. 1994年1月:Python 1.0正式发布。
4. 2000年10月16日:Python 2.0发布,增加了完整的垃圾回收,提供了对Unicode的支持。与此同时,Python的整个开发过程更加透明,社区对开发进度的影响逐渐扩大,生态圈开始慢慢形成。
5. 2008年12月3日:Python 3.0发布,它并不完全兼容之前的Python代码,不过因为目前还有不少公司在项目和运维中使用Python 2.x版本,所以Python 3.x的很多新特性后来也被移植到Python 2.6/2.7版本中。
6.2009年6月:Python发布3.1了版本。
7.2011年2月:Python发布3.2了版本。
8.2012年9月:Python发布3.3了版本。
9.2014年3月:Python发布了3.4版本。
10.2015年9月:Python发布了3.5版本。
11.2016年12月:Python发布了3.6版本。
目前我们使用的Python 3.7.x的版本是在2018年发布的,Python的版本号分为三段,形如A.B.C。其中A表示大版本号,一般当整体重写,或出现不向后兼容的改变时,增加A;B表示功能更新,出现新功能时增加B;C表示小的改动(例如:修复了某个Bug),只要有修改就增加C。如果对Python的历史感兴趣,可以阅读名为《Python简史》的博文。
Python的优点很多,简单的可以总结为以下几点。
Python的缺点主要集中在以下几点。
1. 执行效率稍低,因此计算密集型任务可以由C/C++编写。
2. 代码无法加密,但是现在很多公司都不销售卖软件而是销售服务,这个问题会被弱化。
3. 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误。
1. python3中,print不再是关键字,而是函数,
2. 比如原来是 print ‘abc’ 现在是 print(‘abc’)但是 python2.6+ 可以使用 from future import print_function 来实现相同功能
3. 在Python 3中,没有旧式类,只有新式类,
4. 原来1/2(两个整数相除)结果是0,现在是0.5了,
5. 新的字符串格式化方法format取代%,从 python2.6+ 开始已经在str和unicode中有该方法, 同时 python3依然支持 % 算符
6. 对 bytes 和 原生 UNICODE 字符串的支持, 删除了 unicode 对象, str 为原生 unicode 字符串, bytes 替代了之前的 str.
7. xrange重命名为range。同时更改的还有一系列内置函数及方法, 都返回迭代器对象, 而不是列表或者 元组, 比如 filter, map, dict.items 等
8. != 取代 < > 在python2中 也很少有人用 < > 所以影响不大
9. 某些类库的变化,组织结构变了些. 但功能没变. urlparse - > urllib.parse 这样的变化
1 | import this |
《三十六计》或称三十六策,是指中国古代三十六个兵法策略,语源于南北朝,成书于明清。它是根据中国古代军事思想和丰富的斗争经验总结而成的兵书,是中华民族悠久非物质文化遗产之一。
原书按计名排列,共分六套,即胜战计、敌战计、攻战计、混战计、并战计、败战计。前三套是处于优势所用之计,后三套是处于劣势所用之计。
处于绝对优势地位之计谋。君御臣、大国御小国之术也。亢龙有悔。
本指光天化日之下不让天知道就过了大海。形容极大的欺骗和谎言,什么样的欺骗手段都使得出来。
【原典】
备周则意怠①;常见则不疑。阴在阳之内,不在阳之对②。太阳,太阴③。
【注释】
兵法:三十六计
①备周则意怠:防备十分周密,往往容易让人斗志松懈,削弱战力。②阴在阳之内,不在阳之对:阴阳是我国古代传统哲学和文化思想的基点,其思想笼罩着大千宇宙、细末尘埃,并影响到意识形态的一切领域。阴阳学说是把宇宙万物作为对立的统一体来看待,表现出朴素的辩证思想。阴、阳二字早在甲骨文、金文中出现过,但作为阴气、阳气的阴阳学说,最早是由道家始祖楚国人老子所倡导,并非《易经》提出。此计中所讲的阴指机密、隐蔽;阳,指公开、暴露。阴在阳之内,不在阳之对,在兵法上是说秘计往往隐藏于公开的事物里,而不在公开事物的对立面上。
③太阳,太阴:太,极,极大。此句指非常公开的事物里往往蕴藏着非常机密的计谋。
【释义】
防备得周全时,更容易麻痹大意;习以为常的事,也常会失去警戒。秘密常潜藏在公开的事物里,并非存在于公开暴露的事物之外。公开暴露的事物发展到极端,就形成了最隐秘的潜藏状态。
【浅解】
所谓瞒天过海,就是故意一而再、再而三地用伪装的手段迷惑、欺骗对方,使对方放松戒备,然后突然行动,从而达到取胜的目的。
【按语】
阴谋作为,不能于背时秘处行之。夜半行窃,僻巷杀人,愚俗之行,非谋士之所为也。如:开皇九年,大举伐陈。先是弼请缘江防人,每交代之际,必集历阳,大列旗帜,营幕蔽野。陈人以为大兵至,悉发国中士马,既而知防人交代。其众复散,后以为常,不复设备,及若弼以大军济江,陈人弗之觉也。因袭南徐州,拔之。
【解析】
“瞒天过海”之谋略决不可以与“欺上瞒下”、“掩耳盗铃”或者诸如夜中行窃、拖人衣裘、僻处谋命之类等同,也决不是谋略之士所应当做的事情。虽然,这两种在某种程度上都含有欺骗性在内,但其动机、性质、目的是不相同的,自是不可以混为一谈。这一计的兵法运用,常常是着眼于人们在观察处理世事中,由于对某些事情的习见不疑而自觉不自觉地产生了疏漏和松懈,故能乘虚而示假隐真,掩盖某种军事行动,把握时机,出奇制胜。
【探源】
见《永乐大典·薛仁贵征辽事略》。唐太宗贞观十七年,御驾亲征,领三十万大军以宁东土。一日,浩荡大军东进来到大海边上,帝见眼前只是白浪排空,海茫无穷,即向众总管问及 过海之计,四下面面相觑。忽传一个近居海上的豪民请求见驾,并称三十万过海军粮此家业已独备。帝大喜,便率百官随这豪 民来到海边。只见万户皆用一彩幕遮围,十分严密。豪民老人东向倒步引帝入室。室内更是绣幔彩锦,茵褥铺地。百官进酒, 宴饮甚乐。不久,风声四起,波响如雷,杯盏倾侧,人身摇动,良久不止。太宗警惊,忙令近臣揭开彩幕察看,不看则已,一 看愕然。满目皆一片清清海水横无际涯,哪里是什么在豪民家作客,大军竟然已航行在大海之上了!原来这豪民是新招壮士薛仁贵扮成,这“瞒天过海”计策就是他策划的。 “瞒天过海”用在兵法上,实属一种示假隐真的疑兵之计, 用来作战役伪装,以期达到出其不意的战斗成果。
【故事】
公元589年,隋朝将大举攻打陈国。这陈国乃是公元557年陈霸先称帝建国,定国号为陈,建都城于建康,也就是今天的南京。战前,隋朝将领贺若弼因奉命统领江防,经常组织沿江守备部队调防。每次调防都命令部队于历阳(也就是今天安徽省和县一带地方)集中。还特令三军集中时,必须大列旗帜,遍支警帐,张扬声势,以迷惑陈国。果真陈国难辨虚实,起初以为大军将至,尽发国中士卒兵马,准备迎敌面战。可是不久,又发现是隋军守备人马调防,并非出击,陈便撤回集结的迎战部队。如此五次三番,隋军调防频繁,蛛丝马迹一点不露,陈国竟然也司空见惯,戒备松懈。直到隋将贺若弼大军渡江而来,陈国居然未有觉察。隋军如同天兵压顶,令陈兵猝不及防,遂一举拔取陈国的南徐州(今天的江苏省镇江市一带)。
本指围攻魏国的都城以解救赵国。现借指用包超敌人的后方来迫使它撤兵的战术。
【原典】
共敌不如分敌①,敌阳不如敌阴②。
【注释】
①共敌不如分敌:共,集中的。分,分散,使分散。句意:攻打集中的敌人,不如设法分散它而后再打。
②敌阳不如敌阴:敌,动词,攻打。句意为 先打击气势旺盛的敌人,不如后打击气势旺盛的敌人。
【释义】
进攻兵力集中、实力强大的敌军,不如使强大的敌军分散减弱了再攻击。攻击敌军的强盛部位,不如攻击敌军的薄弱部份来得有效。
【浅解】
所谓围魏救赵,是指当敌人实力强大时,要避免和强敌正面决战,应该采取迂回战术,迫使敌人分散兵力,然后抓住敌人的薄弱环节发动攻击,致敌于死地。
【按语】
治兵如治水:锐者避其锋,如导疏;弱者塞其虚,如筑堰。故当齐救赵 时,孙膑谓田忌曰:“夫解杂乱纠纷者不控拳,救斗者,不搏击,批亢捣虚,形格势禁,则自为解耳。”
【解析】
对敌作战,好比治水:敌人势头强大, 就要躲过冲击,如用疏导之法分流。对弱小的敌人,就抓住时机消灭它,就象筑堤围堰,不让水流走。所以当齐救赵时,孙子对田忌说:“想理顺乱丝和结绳,只能用手指慢慢去解开,不能握紧拳头去捶打;排解搏斗纠纷,只能动口劝说,不能动手参加。对敌人,应避实就虚,攻其要害,使敌方受到挫折,受到牵制,围困可以自解。”
【故事】
公元前354年,赵国进攻卫国,迫使卫国屈服于它。卫国原来是入朝魏国的,后来改向亲附赵国,魏惠王不由十分恼火,于是决定派庞涓讨伐赵国。不到一年时间,庞涓便攻到了赵国的国都邯郸。邯郸危在旦夕。赵国国君赵成侯一面竭力固守,一面派人火速奔往齐国求救(此时,赵国与齐国结盟)。齐威王任命田忌为主将,以孙膑为军师,率军救赵。孙膑出计,要军中最不会打仗的齐城、高唐佯攻魏国的军事要地——襄陵,以麻痹魏军。而大军却绕道直插大梁。庞涓得到魏惠王的命令只得火速返国救援。魏军为疲惫之师,怎能打过齐国以逸待劳的精锐之师。所以大败。
比喻自己不出面,假借别人的手去害人。
【原典】
敌已明,友未定①,引友杀敌,不自出力,以《损》②推演。
【注释】
①友未定:“友”指军事上的盟者,也即除敌、我两方之外的第三者中,可以一时结盟而借力的人、集团或国家。友未定,就是说盟友对主战的双方,尚持徘徊、观望的态度,其主意不明不定的情况。
②《损》:出自《易经·损》卦:“损:有孚,元吉,无咎,可贞,利有攸往。”孚,信用。元,大。贞,正。意即,取抑省之道去行事,只要有诚心,就会有大的吉利,没有错失,合于正道,这样行事就可一切如意。又有《象》损卦:“损:损下益上,其道上行。”意指“损”与“益”的转化关系,借用盟友的力量去打击敌人,势必要使盟友受到损失,但盟友的损失正可以换得自己的利益。
【释义】
敌人的情况已经明了,友方的态度尚未确定。利用友方的力量去消灭敌人,自己不需要付出什么力量。这是从《损》卦推演出的计策。
【浅解】
所谓借刀杀人,是指在对付敌人的时候,自己不动手,而利用第三者的力量去攻击敌人,用以保存自己的实力;再进一步,则巧妙地利用敌人的内部矛盾,使其自相残杀,以达到致敌于死地的目的。
【按语】
敌象已露,而另一势力更张,将有所为,便应借此力以毁敌人。如:郑桓公将欲袭郐,先向郐之豪杰、良臣、辨智、果敢之士,尽书姓名,择郐之良田赂之,为官爵之名而书之,因为设坛场郭门之处而埋之,衅之以鸡缎,若盟状。郐君以为内难也,而尽杀其良臣。桓公袭郐,遂取之。诸葛亮之和吴拒魏,及关羽围樊、裹,曹欲徙都,懿及蒋济说曹曰:“刘备、孙权外亲内疏,关羽得志,权心不愿也。可遣人蹑其后,许割江南以封权,则樊围自释。”曹从之,羽遂见擒。
【故事】
刘秀借刀杀李铁。
指作战时不首先出击,养精蓄锐,以对付从远道来的疲劳的敌人。
【原典】
《三十六计通解与运用》
《三十六计通解与运用》
困敌之势①,不以战;损刚益柔②。【注释】
①困敌之势:迫使敌人处于围顿的境地。
②损刚益柔:语出《易经·损》。“刚”、“柔”是两个相对的事物现象,在一定的条件下相对的两方有可相互转化。“损”,卦名。本卦为异卦相叠(兑下艮上)。上卦为艮,艮为山,下卦为兑,兑为泽。上山下泽,意为大泽浸蚀山根之象,也就说有水浸润着山,抑损着山,故卦名叫损”。“损刚益柔”是根据此卦象讲述“刚柔相推,而主变化”的普遍道理和法则。 此计正是根据“损”卦的道理,以“刚”喻敌,以“柔”喻已,意谓困敌可用积极防御,逐渐消耗敌人的有生力量,使之由强变弱,而我因势利导又可使自己变被动为主动,不一定要用直接进攻的方法,同样可以制胜。
【按语】
此即致敌之法也。兵书云:“凡先处战地而待敌者逸,后处战地而趋战者劳。故善战者,致人而不致于人。”兵书论敌,此为论势,则其旨非择地以待敌;而在以简驭繁,以不变应变,以小变应大变,以不动应动以小动应大动,以枢应环也。如:管仲寓军令于内政,实而备之;孙膑于马陵道伏击庞涓;李牧守雁门,久而不战,而实备之,战而大破匈奴。
【故事】
三国时,吴国杀了关羽,刘备怒不可遏,亲自率领七十万大军伐吴。蜀军从长江上游顺流进击,居高临下,势如破竹。举兵东下,连胜十余阵,锐气正盛,直至彝陵,哮亭一带,深入吴国腹地五六百里。孙权命青年将领陆逊为大都督,率五万人迎战。陆逊深谙兵法,正确地分析了形势,认为刘备锐气始盛,并且居高临下,吴军难以进攻。于是决定实行战略退却,以观其变。吴军完全撤出山地,这样,蜀军在五六百里的山地一带难以展开,反而处于被动地位,欲战不能,兵疲意阻。相持半年,蜀军斗志松懈。陆逊看到蜀军战线绵延数百里,首尾难顾,在山林安营扎寨,犯了兵家之忌。时机成熟,陆逊下令全面反攻,打得蜀军措手不及。陆逊—把火,烧毁蜀军七百里连营,蜀军大乱,伤亡惨重,慌忙撤退。陆逊创造了战争史上以少胜多、后发制人的著名战例。
本指趁人家失火的时候去抢东西。现比喻乘人之危,捞一把。
【原典】
敌之害大①,就势取利,刚决柔也②。
【注释】
①敌之害大:害,指敌人所遭遇到的困难,危厄的处境。
②刚决柔也:语出《易经·夬》卦。 夬,卦名。本卦为异卦相叠(乾下兑上)。上卦为兑,兑为泽;下卦为乾,乾为天。兑上乾下,意为有洪水涨上天之象。《夬夬》的《彖》辞说:“央,决也。刚决柔也。”决,冲决、冲开、去掉的意思。因乾卦为六十四卦的第一卦,乾为天,是大吉大利,吉利的贞卜,所以此卦的本义是力争上游,刚健不屈。所谓刚决柔,就是下乾这个阳刚之卦,在冲决上兑这个阴柔的卦。此计是以“刚”喻己,以“柔”喻敌,言乘敌之危,就势而取胜的意思。
【按语】
敌害在内,则劫其地;敌害在外,则劫其民;内外交害,败劫其国。如:越王乘吴国内蟹稻不遗种而谋攻之,后卒乘吴北会诸侯于黄池之际,国内空虚,因而捣之,大获全胜。
【故事】
多尔衮趁乱入关。
指表面上声言要攻打东面,其实是攻打西面。军事上使敌人产生错觉的一种战术。
【原典】
敌志乱萃①,不虞②,坤下兑上 ③之象,利其不自主而取之。
【注释】
①敌志乱萃:援引《易经.萃》卦中《象》辞:“乃乱乃萃,其志乱也”之意。萃,悴,即憔悴。是说敌人情志混乱而且憔悴。
②不虞:未意科,未预料。
③坤下兑上:萃卦为异卦相叠(坤下兑上)。上卦为兑,兑为泽;下并为坤,坤为地。有泽水淹及大地,洪水横流之象。
此计是运用“坤下兑上”之卦象的象理,喻“敌志乱萃”而造成了错失丛杂、危机四伏的处境,我则要抓住敌人这不能自控的混乱之势,机动灵活地运用时东时西,似打似离,不攻而示它以攻,欲攻而又示之以不攻等战术,进一步造成敌人的错觉,出其不意地一举夺胜。
【按语】
西汉,七国反,周亚夫坚壁不战。吴兵奔壁之东南陬,亚夫便备西北;已而吴王精兵果攻西北,遂不得入。此敌志不乱,能自去也。汉末,朱隽围黄巾于宛,张围结垒,起土山以临城内,鸣鼓攻其西南,黄巾悉众赴之,隽自将精兵五千,掩其东北,遂乘虚而入。此敌志乱萃,不虞也。然则声东击西之策,须视敌志乱否为定。乱,则胜;不乱,将自取败亡,险策也。
【故事】
韩信木罂渡黄河。
处于势均力敌态势之计谋。或跃于渊。
本指本来没有却硬说有。现形容凭空捏造。
【原典】
诳也,非诳也,实其所诳也①。少阴、太阴、太阳②。
【注释】
①诳也,非诳也,实其所诳也:诳,欺诈、诳骗。实,实在,真实,此处作意动词。句意为:运用假象欺骗对方,但并非一假到底,而是让对方把受骗的假象当成 真象。
②少阴,太阴,太阳:此“阴”指假象,“阳”指真象。 句意为:用大大小小的假象去掩护真象。
【按语】
无而示有,诳也。诳不可久而易觉,故无不可以终无。无中生有,则由诳而真,由虚而实矣,无不可以败敌,生有则败敌矣,如:令狐潮围雍丘,张巡缚嵩为人千余,披黑夜,夜缒城下;潮兵争射之,得箭数十万。其后复夜缒人,潮兵笑,不设备,乃以死士五百砍潮营,焚垒幕,追奔十余里。
【故事】
张仪诓楚助强秦。
指正面迷惑敌人,而从侧翼进行突然袭击。比喻暗中进行活动。 后多比喻暗中进行某种活动(多指男女私通)。
【原典】
示之以动①,利其静而有主,“益动而巽②”。
【注释】
①示之以动:示,给人看。动,此指军事上的正面佯攻、佯动等迷惑敌方的军事行动。
②益动而巽:语出《易经.益》卦。益,卦名。此卦为异卦相叠(震下巽上)。上卦为巽,巽为风;下卦为震,震为雷。意即风雷激荡,其势愈增,故卦名为益。与损卦之义,互相对立,构成一个统一的组纷。《益卦》的《彖》辞说:“益动而巽,日进无疆。”这是说益卦下震为雷为动,上巽为风为顺,那么,动而合理,是天生地长,好处无穷。
此计是利用敌人被我“示之以动”的迷惑手段所蒙蔽,而我即乘虚而入,以达军事上的出奇制胜。
【按语】
奇出于正,无正不能出奇。不明修栈道,则不能暗渡陈仓。昔邓艾屯白水之北;姜维遥廖化屯白水之南,而结营焉。艾谓诸将日:“维令卒还,吾军少,法当来渡,而不作桥,此维使化持我.令不得还。必自东袭取洮城矣。”艾即夜潜军,径到洮城。维果来渡。而艾先至,据城,得以不破。此则是姜维不善用暗渡陈仓之计;而邓艾察知其声东击西之谋也。
【故事】
韩信奇兵取三秦。
隔着河看对岸的火。比喻对别人的危难不予援救而在一旁看热闹。
【原典】
阳乖序乱①,阴以待逆②。暴戾恣睢③,其势自毙。顺以动豫,豫顺以动④。
【注释】
①阳乖序乱:阳,指公开的。乖,违背,不协调。此指敌方内部矛盾激化,以致公开地表现出多方面秩序混乱、倾轧。
②阴以待逆:阴,暗下的。逆,叛逆。此指暗中静观敌变,坐待敌方更进一步的局面恶化。
③暴戾恣睢:戾,凶暴,猛烈。睢,任意胡为。
④顺以动豫,豫顺以动:语出《易经.豫》卦。豫,卦名。本卦为异卦相叠(坤下震上)。本卦的下卦为坤为地,上卦为震为雷。是雷生于地,雷从地底而出,突破地面,在空中自在飞腾。《豫卦》的《彖》辞说“豫,刚应而志行,顺以动。”意即豫卦的意思是顺时而动,正因为豫卦之意是顺时而动,所以天地就能随和其意,做事就顺当自然。
此计正是运用本卦顺时以动的哲理,说坐观敌人的内部恶变,我不急于采取攻逼手段,顺其变,“坐山观虎斗”,最后让敌人自残自杀,时机—到而我即坐收其利,一举成功。
【按语】
乖气浮张,逼则受击,退则远之,则乱自起。昔袁尚、袁熙奔辽东,众尚有数千骑。初,辽东太守公孙康,恃远不服。及曹操破乌丸,或说曹遂征之,尚兄弟可擒也。操曰:“吾方使斩送尚、熙首来,不烦兵矣。”九月,操引兵自柳城还,康即斩尚、熙,传其首。诸将问其故,操日:“彼素畏尚等,吾急之,则并力;缓之,则相图,其势然也。”或曰:此兵书火攻之道也,按兵书《火攻篇》前段言火攻之法,后段言慎动之理,与隔岸观火之意,亦相吻合。
【故事】
郭嘉定计灭袁氏。
比喻外表和气而内心阴险。
【原典】
信而安之①,阴以图之②,备而后动, 勿使有变。刚中柔外也③。
【注释】
①信而安之:信,使信。安,使安,安然,此指不生 疑心。
②阴以图之:阴,暗地里。
③刚中柔外:表面柔顺,实质强硬尖利。
【按语】
兵书云:“辞卑而益备者,进也;……无约而请和者,谋也。”故凡敌人之巧言令色,皆杀机之外露也。宋曹玮知渭州,号令明肃,西夏人惮之。一日玮方对客弈棋,会有叛夸数千,亡奔夏境。堠骑(骑马的侦宿员)报至,诸将相顾失色,公言笑如平时。徐谓骑日.“吾命也,汝勿显言。”西夏人闻之,以为袭己,尽杀之。此临机应变之用也。若勾践之事夫差.则意使其久而安之矣。
【故事】
隋文帝智灭南陈。
原指桃、李共患难。比喻兄弟相爱相助。后用来指互相顶替或代人受过。
【原典】
势必有损,损阴以益阳①。
【注释】
①损阴以益阳:阴:此指某些细微的、局部的事物。阳,此指事物带整体意义的、全局性的事物。这是说在军事谋略上,如果暂时要以某种损失、失利为代价才能最终取胜,指挥者应当机立断,作出某些局部、或暂时的牺牲,去保全或者争取全局的、整体性的胜利。这是运用我国古代阴阳学说的阴阳相生相克、相互转化的道理而制定的军事谋略。
【按语】
我敌之情,各有长短。战争之事,难得全胜,而胜负之诀,即在长短之相较,乃有以短胜长之秘诀。如以下驷敌上驷,以上驷敌中驷,以中驷敌下驷之类:则诚兵家独具之诡谋,非常理之可测也。
【故事】
三叉用计保孤儿。
顺手就牵了羊。比喻不费劲,乘机便得到的。现多指乘机拿走人家东西的偷窃行为。
【原典】
微隙在所必乘①;微利在所必得。少阴,少阳②。
【注释】
①微隙在所必乘:微隙,微小的空隙,指敌方的某些漏洞、疏忽。
②少阴,少阳:少阴,此指敌方小的疏漏,少阳,指我方小的得利。此句意为我方要善于捕捉时机,伺隙捣虚,变敌方小的疏漏而为我方小的得利。
【按语】
大军动处,其隙甚多,乘间取利,不必以胜。胜固可用,败亦可用。
【故事】
追废帝郑和下西洋。
第三套 攻战计
处于进攻态势之计谋。飞龙在天。
打动草惊动了藏在草里的蛇。后用以指做事不周密,行动不谨慎,而使对方有所觉察。
【原典】
疑以叩实①,察而后动; 复者,阴之媒也②。
【注释】
①疑以叩实:叩,问,查究。意为发现了疑点就应 当考实查究清楚。
②复者,阴之媒也:复者,反复去做,即反复去叩实而后动。阴,此指某些隐藏着的、暂时尚不明显或未暴露的事物、情况。媒,媒介。句意为反复叩实查究,而后采取相应的行动,实际是发现隐藏之敌的重要手段。
【按语】
敌力不露,阴谋深沉,未可轻进,应遍探其锋。兵书云:“军旁有险阻、潢井、葭苇、山林、翳荟者,必谨复索之,此伏奸所藏也。”
【故事】
魏军兵败木门道。
迷信人认为人死后灵魂可附着于别人的尸体而复活。后用以比喻已经消灭或没落的事物,又假托别的名义或以另一种形式重新出现。
【原典】
有用者,不可借①;不能用者,求借②。借不能用者而用之,匪我求童蒙,童蒙求我③。
【注释】
①有用者,不可借;意为世间许多看上去很有用处的东西,往往不容易去驾驭而为己用。
②不能用者,求借:此句意与①句相对言之。即有些看上去无什用途的东西,往往有时我还可以借助它而为己发挥作用。犹如我欲“还魂”还必得借助看似无用的“尸体”的道理。此言兵法,是说兵家要善于抓住一切机会,甚至是看去无什用处的东西,努力争取主动,壮大自己,即时利用而转不利为有利,乃至转败为胜。
③匪我求童蒙,童蒙求我:语出《易经.蒙》卦。蒙,卦名。本纷是异卦相叠(下坎上艮)。本卦上卦为艮为山,下卦为坎为水为险。山下有险,草木丛生,故说“蒙”。这是蒙卦卦象。这里“童蒙”是指幼稚无知、求师教诲的儿童。此句意为不是我求助于愚昧之人,而是愚昧之人有求于我了。
【按语】
换代之际,纷立亡国之后者,固借尸还境之意也。凡—切寄兵权于人,而代其攻宁者,皆此用也。
【故事】
立张楚陈胜为王。
设法使老虎离开山头。比喻为了便于行事,想法子引诱人离开原来的地方。
【原典】
待天以困之①,用人以诱之②,往蹇来连返③。
【注释】
①待天以困之:天,指自然的各种条件或情况。此句意为战场上我方等待天然的条件或情况对敌方不利时,我再去围困他。
②用人以诱之:用人为的假象去诱惑他(指敌人),使他向我就范。
③往蹇来返:语出《易经.蹇》卦。蹇,卦名。本卦为异卦相叠(艮下坎上)。上卦为坎为水,下卦为艮为山。山上有水流,山石多险,水流曲折,言行道之不容易,这是本卦的卦象。蹇,困难;返,广大美好貌。这句意为:去时艰难,来时美好。
此计运用这个道理,是说战场上若遇强敌,要善用谋,用假象使敌人离开驻地,诱他就我之范,丧失他的优势,使他处处皆难,寸步难行,由主动变被动,而我则出其不意而致胜。
【按语】
兵书曰:“下政攻城”。若攻坚,则自取败亡矣。敌既得地利,则不可争其地。且敌有主而势大:有主,则非利不来趋;势大,则非天人合用,不能胜。汉末,羌率众数千,遮虞诩于队仓崤谷。诩即停军不进,而宣言上书请兵,须到乃发。羌闻之,乃分抄旁县。翔因其兵散,日夜进道,兼行百余里,令军士各作两灶,日倍增之,羌不敢逼,遂大破之。兵到乃发者,利诱之也;日夜兼进者,用天时以困之也;倍增其灶者,惑之以人事也。
【故事】
石碏设计除暴君。
石刻:欲擒故纵
石刻:欲擒故纵
要捉住他,故意先放开他。比喻为了进一步的控制,先故意放松一步。【原典】
逼则反兵;走则减势①。紧随勿迫。累其气力,消其斗志,散而后擒,兵不血刃②。需,有孚,光③。
【注释】
①逼则反兵,走则减势:走,跑。逼迫敌人太紧,他可能因此拼死反扑,若让他逃跑则可减削他的气势。
②兵不血刃:血刃,血染刀刃。此句意为兵器上不 沾血。
②需,有孚,光:语出《易经.需卦》。需,卦名。本卦为异卦相叠(乾下坎上)。需的下卦为乾为天,上卦为坎为水,是降雨在即之象。也象征着一种危险存在着(因为“坎”有险义),必得去突破它,但突破危险又要善于等待。“需”,等待。《易经,需》卦卦辞:“需,有孚,光”。孚,诚心。光,通广。句意为:要善于等待,要有诚心(包含耐性),就会有大吉大利。
【按语】
所谓纵着,非放之也,随之,而稍松之耳。“穷寇勿追”,亦即此意,盖不追者,非不随也,不追之而已。武侯之七纵七擒,即纵而随之,故蹑展转推进,至于不毛之地。武侯之七纵,其意在拓地,在借孟获以服诸蛮,非兵法也。故论战,则擒者不可复纵。
【故事】
诸葛亮七擒孟获。
以自己的粗浅的意见引出别人高明的见解。
【原典】
类以诱之①,击蒙也②。
【注释】
①类以诱之:出示某种类似的东西并去诱惑他。
②击蒙也:语出《易经.蒙》如。参前“借尸还魂”计注释④。击,撞击,打击。句意为:诱惑敌人,便可打击这种受我诱惑的愚蒙之人了。
【按语】
诱敌之法甚多,最妙之法,不在疑似之间,而在类同,以固其惑。以旌旗金鼓诱敌者,疑似也;以老弱粮草诱敌者,则类同也。如:楚伐绞,军其南门,屈瑕曰:“绞小而轻,轻则寡谋,请勿捍采樵者以诱之。”从之,绞人获利。明日绞人争出,驱楚役徙于山中。楚人坐守其北门,而伏诸山下,大败之,为城下之盟而还。又如孙膑减灶而诱杀庞涓。
【故事】
萧翼智赚《兰亭序》帖。
作战要先擒拿主要敌手。比喻做事要抓关键。
【原典】
摧其坚,夺其魁,以解其体。龙战于野,其道穷也①。
【注释】
①龙战于野,其道穷也:语出《易经.坤》卦。坤,卦名。本卦是同卦相叠(坤下坤上),为纯阴之卦。引本卦上六,《象辞》:“龙战于野,其道穷也。”是说即使强龙争斗在田野大地之上,也是走入了困顿的绝境。比喻战斗中擒贼擒王谋略的威力。
【按语】
攻胜则利不胜取。取小遗大,卒之利、将之累、帅之害、攻之亏也。舍胜而不摧坚擒王.是纵虎归山也。擒王之法,不可图辨旌旗,而当察其阵中之首动。昔张巡与尹子奇战,直冲敌营,至子奇麾下,营中大乱,斩贼将五十余人,杀士卒五千余人。迎欲射子奇而不识,剡蒿为矢,中者喜谓巡矢尽,走白子奇,乃得其状,使霁云射之,中其左目,几获之,子奇乃收军退还。
【故事】
西门豹治邺。
处于不分敌友、军阀混战态势之计谋。见龙在野。
从锅底抽掉柴火。比喻从根本上解决问题。
【原典】
不敌其力①,而消其势②,兑下乾上之象③。
【注释】
①不敌其力:敌,动词,攻打。力,最坚强的部位。
②而消其势:势,气势。
③兑下乾上之象:《易经》六十四卦中,《履》卦为 “兑下乾上”,上卦为乾为天.下卦为兑为泽。又,兑为阴卦,为柔;乾为阳卦,为刚。兑在下,从循环关系和规律上说,下必冲上,于是出现“柔克刚”之象。此计正是 运用此象推理衍之,喻我取此计可胜强敌。
【按语】
水沸者,力也,火之力也,阳中之阳也,锐不可当;薪者,火之魄也,即力之势也,阴中之阴也,近而无害;故力不可当而势犹可消。尉缭子曰:“气实则斗,气夺则走。”面夺气之法,则在攻心,昔吴汉为大司马,有寇夜攻汉营,军中惊扰,汉坚卧不动,军中闻汉不动,有倾乃定。乃选精兵反击,大破之:此即不直当其力而扑消其势也。宋薛长儒为汉、湖、滑三州通判,驻汉州。州兵数百叛,开营门,谋杀知州、兵马监押,烧营以为乱。有来告者,知州、监押皆不敢出。长儒挺身徒步,自坏垣入其营中,以福祸语乱卒日:“汝辈皆有父母妻子,何故作此?叛者立于左,胁从者立于右!”于是,不与谋者数百人立于右;独主谋者十三人突门而出,散于诸村野,寻捕获。时谓非长儒,则一城涂炭矣!此即攻心夺气之用也。或日:敌与敌对,捣强敌之虚以败其将成之功也。
【故事】
曹操奇兵袭乌巢。
比喻趁混乱时机攫取不正当的利益。也作“浑水摸鱼”。
【原典】
乘其阴乱①,利其弱而无主。随,以向晦入宴息②。
【注释】
①乘其阴乱:阴,内部。意为乘敌人内部发生混乱。
②随,以向晦入宴息:语出《易经.随》卦。随,卦名。本卦为异卦相叠(震下兑上)。本卦上卦为兑为泽;下卦为震为雷。言雷入泽中,大地寒凝,万物蛰伏,故如象名“随”。随,顺从之意。《随卦》的《象》辞说:“泽中有雷,随,君子以向晦入宴息。”意为人要随应天时去作息,向晚就当入室休息。
此计运用此象理,是说打仗时要得于抓住敌方的可乘之隙,而我借机行事,使乱顺我之意,我便乱中取利。
【按语】
动荡之际,数力冲撞,弱者依违无主,散蔽而不察,我随而取之。《六韬》日:“三军数惊,士卒不齐,相恐以敌强,相语以不利,耳目相属,妖言不止,众口相惑,不畏法令,不重其将:此弱征也。”是鱼,混战之际,择此而取之。如:刘备之得荆州,取西川,皆此计也。
【故事】
搅乱局淝水败苻坚。
蝉变为成虫时要脱去幼早的壳。比喻用计脱身。
【原典】
存其形,完其势①;友不疑,敌不动。巽而止蛊②。
【注释】
①存其形,完其势,保存阵地已有的战斗形貌,进一步完备继续战斗的各种态势。
②巽而止蛊:语出《易经·蛊》卦。蛊,卦名。本卦为异卦相叠(巽下艮上)。本卦上卦为艮为山为刚,为阳卦;巽为风为柔,为阴势。故“蛊”的卦象是“刚上柔下”,意即高山沉静,风行于山下,事可顺当。又,艮在上卦,为静;巽为下卦,为谦逊,故说“谦虚沉静”,“弘大通泰”是天下大治之象。
此计引本卦《彖》辞:“巽而止,蛊。”其意是我暗中谨慎地实行主力转移,稳住敌人,我则乘敌不惊疑之际脱离险境,就可安然躲过战乱之危。“蛊”,意为顺事。
【按语】
共友击敌,坐观其势。尚另有一敌,则须去而存势。则金蝉脱壳者,非徒走也,盖为分身之法也。故大军转动.而旌旗金鼓,俨然原阵,使敌不敢动,友不生疑,待己摧他敌而返,而友敌始知,或犹且不如。然则金蝉脱壳者,在对敌之际,而抽精锐以袭别阵也。如:诸葛亮卒于军,司马懿追焉,姜维令仪反旗鸣鼓,若向懿者,懿退,于是仪结营而去。檀道济被围,乃命军士悉甲,身自(白)服乘舆徐出外围,魏惧有伏,不敢逼,乃归。
【故事】
慈禧用计回北京。
关起门来捉进入屋内的盗贼。
【原典】
小敌困之①。剥,不利有攸往②。
【注释】
①小敌困之:对弱小或者数量较少的敌人,要设法去困围(或者说歼灭)他。
②剥,不利有攸往:语出《易经.剥》卦。剥,卦名。本卦异卦相叠(坤下艮上),上卦为艮为山,下卦为坤为地。意即广阔无边的大地在吞没山,故外名日“剥”。“剥”,落的意思。卦辞:“剥,不利有彼往”意为:剥卦说,有所往则不利。
此计引此卦辞,是说对小股敌人要即时围困消灭,而不利于去急追或者远袭。
【按语】
捉贼而必关门,非恐其逸也,恐其逸而为他人所得也;且逸者不可复追,恐其诱也。贼署,奇兵也,游兵也,所以劳我者也。吴子曰:“今使一死贼,伏于矿野,千人追之,莫不枭视狼顾。何者?恐其暴起而害己也。是以—人投命,足惧千夫。”追贼者,贼有脱逃之机,势必死斗;若断其去路,则成擒矣。故小敌必困之,不能,则放之可也。
【故事】
白起长平败赵括。
石刻:远交近攻
石刻:远交近攻
结交离得远的国家而进攻邻近的国家。这是秦国用以并吞六国,统一全国的外交策略。【原典】
形禁势格①,利从近取,害以远隔②。上火下泽③。
【注释】
①形禁势格:禁,禁止。格,阻碍。句意为受到地势的限制和阻碍。
②利从近取,害以远隔:句意为,先攻取就近的敌人有利,越过近敌先去攻取远隔之敌是有害的。
③上火下泽:语出《易经·睽》卦。睽,卦名。本卦为异卦相叠(兑下离上)。上卦为离为火,下卦为兑为泽。上离下泽,是水火相克,水火相克则又可相生,循环无穷。又“睽”,乘违,即矛盾。本卦《象》辞:“上火下泽,睽。”意为上火下泽,两相离违、矛盾。
此计运用“上火下泽”相互离违的道理,说明采取“远交近攻”的不同做法,使敌相互矛盾、离违,而我正好各个击破。
【按语】
混战之局,纵横捭阖之中,各自取利。远不可攻,而可以利相结;近者交之,反使变生肘腑。范雎之谋,为地理之定则,其理甚明。
【故事】
定国策范雎拜相。
以借路为名,实际上要侵占该国(或该路)。虢,诸侯国名。也作“假道灭虢”。
【原典】
两大之间,敌胁以从,我假以势①。困,有言不信②。
【注释】
①两大之间,敌胁以从,我假以势:假,借。句意为:处在我与敌两个大国之中的小国,敌方若胁迫小国屈从于他时,我则要借机去援救,造成一种有利的军事态势。
②困,有言不信:语出《易经·困》卦。困,卦名。本纷为异卦相叠(坎下兑上),上卦为兑为泽,为阴;下卦为坎为水,为阳。卦象表明,本该容纳于泽中的水,离开泽而向下渗透,以致泽无水而受困,水离开泽流散无归也自困,故卦名为“困”。“困”,困乏。卦辞:“困,有言不信。”意为,处在困乏境地,难道不相信这基吗?此计运用此卦理,是说处在两个大国中的小国,面临着受人胁迫的境地时,我若说援救他,他在困顿中会不相信吗?
【按语】
假地用兵之举,非巧言可诳,必其势不受—方之胁从,则将受双方之夹击。如此境况之际,敌必迫之以威,我则诳之以不害,利其幸存之心,速得全势,彼将不能自阵,故不战而灭之矣。如:晋侯假道于虞以伐虢,晋灭虢,虢公丑奔京师,师还,袭虞灭之。
【故事】
蠢虞公贪财丧国。
对付友军反为敌态势之计谋。终日乾乾。
比喻暗中玩弄手法,以假代真。
【原典】
频更其阵,抽其劲旅,待其自败, 而后乘之①,曳其轮也②。
【注释】
①句中的几个“其”字,均指盟友、盟军言之。
②曳其轮也:“语出《易经,既济》纷。既济,龄名,本卦为异卦相叠(离下坎上)。上卦为坎为水,下卦为离为火。水处火上,水势压倒火势,救火之事,大告成功,故卦名“即济”。既,已经;济,成功。本卦初九?《象》辞:“曳其轮,义无咎也。”意为,拖住了车轮,车子就不能运行了。
此计运用此象理,是说好比拖住了车轮,车子就不能运行了。己方抽其友方劲旅,如同抽出梁木,房屋就会坍塌,于是己方就可以控制他了。
【按语】
阵有纵横,天衡为梁,地轴为柱。梁柱以精兵为之,故观其阵,则知精兵之所有。共战他敌时,频更其阵,暗中抽换其精兵,或竟代其为梁柱;势成阵塌,遂兼其兵。并此敌以击他敌之首策也。
【故事】
狸猫换太子。
指着桑树骂槐树。比喻借题发挥,指着这个骂那个。
【原典】
大凌小者,警以诱之①。刚中而应,行险而顺②。
【注释】
①大凌小者,警以诱之:强大者要控制弱下者,要用警戒的办法去诱导他。
②刚中而应,行险而顺:语出《易经.师》卦。师卦名。本卦为异卦相叠(坎下坤上)。本卦下卦为坎为水,上卦为坤为地,水流地下,随势而行。这正如军旅之象,故名为“师”。本卦《彖》辟说:“刚中而应,行险而顺,以此毒天下,而民从之。”“刚中而应”是说九二以阳爻居于下坎的中信,叫“刚中”,又上应上坤的六五,此为此应。下卦为坎,坎表示险,上卦为坤,坤表示顺,故又有“行险而顺”之象。以此卦象的道理督治天下,百姓就会服从。这是吉祥之象。“毒”,督音,治的意思。
此计运用此象理,是说治军,有时采取适当的强刚手段便会得到应和,行险则遇顺。
【按语】
率数未服者以对敌,若策之不行,而利诱之,又反启其疑,于是故为自误,责他人之失,以暗警之。警之者,反诱之也。此盖以刚险驱之也。或曰:此遣将之法也。
【故事】
严军纪穰苴斩庄贾。
假装痴呆,掩人耳目,另有所图。
【原典】
宁伪作不知不为,不伪作假知妄为①。静不露机,云雷屯也②。
【注释】
①宁伪作不知不为,不伪作假知妄为:宁可假装着无知而不行动,不可以假装假知而去轻举妄动。
②静不露机,云雷屯也:语出《易经.屯》卦。屯卦名。本卦为异卦相叠(震下坎上),震为雷,坎为雨,此卦象为雷雨并作,环境险恶,为事困难。“屯,难也”。《屯卦》的《彖》辞又说“云雷,屯。”坎为雨,又为云,震为雷。这是说,云行于上,雷动于下,云在上有压抑雷之象征,这是屯卦之卦象。
此计运用此象理,是说在军事上,有时为了以退求进,必得假痴不癫,老成持重,以达后发制人。这就如同云势压住雷动,且不露机巧一样,最后一旦爆发攻击,便出其不意而获胜。
【按语】
假作不知而实知,假作不为而实不可为,或将有所为。司马懿之假病昏以诛曹爽,受巾帼假请命以老蜀兵,所以成功;姜维九伐中原,明知不可为而妄为之,则似痴矣,所以破灭。兵书曰:“故善战者之胜也,无智名,无勇功。”当其机未发时,静屯似痴;若假癫,则不但露机,则乱动而群疑。故假痴者胜,假癫者败。或日:假痴可以对敌,并可以用兵。宋代,南俗尚鬼。狄青征侬智高时,大兵始出桂林之南,因佯祝曰:“胜负无以为据。”乃取百钱自持,与神约,果大捷,则投此钱尽钱面也。左右谏止,傥不如意,恐沮师,青不听。万众方耸视,已而挥手一掷,百钱旨面。于是举兵欢呼,声震林野,青亦大喜;顾左右。取百丁(钉)来,即随钱疏密,布地而帖丁(钉)之,加以青纱笼,手自封焉。曰:“俟凯旋,当酬神取钱。”其后平邕州还师,如言取钱,幕府士大夫共祝视,乃两面钱也。
【故事】
燕王装疯夺皇权。
上楼以后拿掉梯子。借指与人密谈。也用以比喻怂恿人,使人上当。
【原典】
假之以便,唆之使前,断其援应,陷之死地①。遇毒,位不当也②。
【注释】
①假之以便,唆之使前,断其援应,陷之死地:假,借。句意:借给敌人一些方便(即我故意暴露出一些破绽),以诱导敌人深入我方,乘机切断他的后援和前应,最终陷他于死地。
②遇毒,位不当也:语出《易经.噬嗑》卦。噬嗑,卦名。本卦为异卦相叠(震下离上)。上卦为离为火,下卦为震为雷,是既打雷,又闪电,威严得很。又离为阴卦,震为阳卦,是阴阳相济,刚柔相交,以喻人要恩威并用,严明结合,故封名为“噬嗑”,意为咀嚼。本卦六三.《象》辞:“遇毒,位不当也。”本是说,抢腊肉中了毒(古人认为腊肉不新鲜,含有毒素,吃了可能中毒),因为六三阴兑爻于阳位,是位不当。
此计运用此理,是说敌人受我之唆,犹如贪食抢吃,只怪自己见利而受骗,才陷于了死地。
【按语】
唆者,利使之也。利使之而不先为之便,或犹且不行。故抽梯之局,须先置梯,或示之梯。如:慕容垂、姚苌诸人怂秦苻坚侵晋,以乘机自起。
【故事】
刘琦登楼求妙计。
比喻将本求利,别人收获。语出《荡寇志》。
【原典】
借局布势,力小势大①。鸿渐于陆,其羽可用为仪也②。
【注释】
①借局布势,力小势大:句意为借助某种局面(或手段)布成有利的阵势,兵力弱小但可使阵势显出强大的样子。
②鸿渐于陆,其羽可用为仪:语出《易经.渐》卦。渐,卦名,本卦为异卦相叠(艮下巽上).上卦为巽为木,下卦为艮为山。卦象为木植长于山上,不断生长,也喻人培养自己的德性,进而影响他人,渐,即渐进。本卦上九说“鸿渐于陆,其羽可为仪,吉利,”是说鸿雁走到山头,它的羽毛可用来编织舞具这是吉利之兆。
此计运用此理,是说弱小的部队通过凭借某种因素,改变外部形态之后,自己阵容显得充实强大了,就象鸿雁长了羽毛丰满的翅膀一样。
【按语】
此树本无花,而树则可以有花,剪彩贴之,不细察者不易发,使花与树交相辉映,而成玲珑全局也。此盖布精兵于友军之阵,完其势以威敌也。
【故事】
田单大摆火牛阵。
本是客人却用主人的口气说话。后指在一定的场合下采取主动措施,以声势压倒别人。
【原典】
乘隙插足,扼其主机①,渐之进也②。
【注释】
①乘隙插足,扼其主机:把准时机插足进去,掌握他的要害关节之处。
②渐之进也:语出《易经.渐》卦。(渐卦解释见前计②)本卦《彖》辞:“渐之进也。”意为渐就是渐进的意思。
此计运用此理,是说乘隙插足,扼其主机。《易经.渐》卦上说的就是这个意思,要循序渐进。
【按语】
为人驱使者为奴,为人尊处者为客,不能立足者为暂客,能立足者为久客,客久而不能主事者为贱客,能主事则可渐握机要,而为主矣。故反客为主之局:第—步须争客位;第二步须乘隙;第三步须插足;第四足须握机;第五乃为主。为主,则并人之军矣;此渐进之阴谋也。如李渊书尊李密,密卒以败;汉高视势未敌项羽之先,卑事项羽。使其见信,而渐以侵其势,至垓下—役,—亡举之。
【故事】
郭子仪单骑退敌。
处于败军态势之计谋,潜龙勿用。
以美女诱人的计策。
【原典】
美人计
美人计
兵强者,攻其将;将智者,伐其情①。将弱兵颓,其势自萎。利用御寇,顺相保也②。【注释】
①兵强者,攻其将;兵智者,伐其情:句意:对兵力强大的敌人,就攻击他的将帅,对明智的敌人,就打击他的情绪。
②利用御寇,顺相保也:语出《易经.渐》卦。(卦名解释见计“树上开花”注②)本身九三《象》辞:“利御寇,顺相保也。”是说利于抵御敌人,顺利地保卫自己。
此计运用此象理,是说利用敌人自身的严重缺点,己方顺势以对,使其自颓自损,己方一举得之。
【按语】
兵强将智,不可以敌,势必事先。事之以土地,以增其势,如六国之事秦:策之最下者也。事之以币帛,以增其富,如宋之事辽金:策之下者也。惟事以美人,以佚其志,以弱其体,以增其下之怨。如勾践以西施重宝取悦夫差,乃可转败为胜。
【故事】
报国仇西施赴吴。
在敌众我寡的情况下,缺乏兵备而故意示意人以不设兵备,造成敌方错觉,从而惊退敌军之事。后泛指掩饰自己力量空虚、迷惑对方的策略。
【原典】
虚者虚之,疑中生疑①;刚柔之际②,奇而复奇。
【注释】
①虚者虚之,疑中生疑:第一个“虚”为名词,意为空虚的,第二个“虚”为
动词,使动,意为让它空虚。全句意:空虚的就让它空虚,使他在疑惑中更加产生
疑惑。
空城计
空城计
②刚柔之际:语出《易经·解》卦。解,卦名。本卦为异卦相叠(坎下震上)。上卦为震为雷,下卦为坎为雨。雷雨交加,荡涤宇内,万象更新,万物萌生,故卦
名为解。解,险难解除,物情舒缓。本卦初六.《象》辞“刚柔之际,义无咎也”,
是使刚与柔相互交会,没有灾难。
【按语】
此计运用此象理,是说敌我交会,相战,运用此计可产生奇妙而又奇妙的功效。
古人按语说:虚虚实实,兵无常势。虚而示虚,诸葛而后,不乏其人。如吐蕃陷瓜州,王君焕死,河西汹惧。以张守归圭为瓜州刺史,领余众,方复筑州城。版干(筑城墙用的夹板和立柱)裁立.敌又暴至。略无守御之具。城中相顾失色,莫有斗志。守圭日:“徒众我寡,又疮痍之后,不可以矢石相持,须以权道制之。”乃于城上,置酒作乐,以会将士。敌疑城中有备,不敢攻而退。又如齐祖铤为北徐州刺史,至州,会有阵寇百姓多反。铤不关城门,守陴者,皆令下城,静座街巷,禁断行人鸡犬。贼无所见闻,不测所以,或疑人走城空,不设警备。铤复令大叫,鼓噪聒天,贼大惊,顿时走散。 [2]
【故事】
失街亭孔明弄险。
原指使敌人的间谍为我所用,或使敌人获取假情报而有利于我的计策。后指用计谋离间敌人引起内讧。
【原典】
疑中之疑①。比之自内,不自失也②。
【注释】
①疑中之疑:句意为在疑阵中再布疑阵。
②比之自内,不自失也:语出《易经·比》卦。比,卦名,本卦为异卦相叠(坤下坎上)。本卦上卦为坎为为相依相赖,故名“比”。比,亲比,亲密相依。本纷六二。《象》辞:“比之自内,不自失也。”
此计运用此象理,是说在布下一重重的疑阵之后,能使来自敌内部的间谍归顺于我。
【按语】
间者,使敌自相疑忌也;反间者,因敌之间而间之也。如燕昭王薨,惠王自为太子时,不快于乐毅。田单乃纵反间曰:“乐毅与燕王有隙,畏诛,欲连兵王齐,齐人未附。故且缓攻即墨,以待其事。齐人唯恐他将来,即墨残矣。惠王闻之,即使骑劫代将,毅遂奔赵。又如周瑜利用曹操间谍,以间其将;陈平以金纵反间于楚军,间范增,楚王疑而去之。亦疑中之疑之局也。
【故事】
群英会蒋干中计。
故意毁伤身体以骗取对方信任,从而进行反间的计谋。
【原典】
人不自害,受害必真;假真真假,间以得行①。童蒙之吉,顺以巽也②。
【注释】
①人不自害,受害为真;假真真假,间以得行:(正常情况下)人不会自我伤害,若他受害必然是真情;(利用这种常理)我则以假作真,以真作假,那么离间计就可实行了。
②童蒙之吉,顺以巽也:语出《易经.蒙》卦(卦名解释见第十四计注)。本卦六五.《象》辞:“童蒙之吉,顺以巽也。”本意是说幼稚蒙昧之人所以吉利,是因为柔顺服从。
本计用此象理,是说用采用这种办法欺骗敌人,就是顺应着他那柔弱的性情达到目的。
【按语】
间者,使敌人相疑也;反间者,因敌人之疑,而实其疑也;苦肉计者,盖假作自间以间人也。凡遣与己有隙者以诱敌人,约为响应,或约为共力者:皆苦肉计之类也。如:郑武公伐胡而先以女妻胡君,并戮关其思;韩信下齐而骊生遭烹。
【故事】
王佐断臂诈投金,黄盖诈降曹操。
本为元杂剧名。剧本写汉末董卓专权,王允设计,先许嫁美女貂蝉与吕布,后又献给董卓,以离间二人,致使吕布杀死董卓。后用以指一个接一个相互关联的计策。
【原典】
将多兵众,不可以敌,使其自累,以杀其势。在师中吉,承天宠也①。
【注释】
①在师中古,承天变也:语出《易经.师》卦(卦名讲释见前第二十六计注)。本卦九二.《象》辞:“在师中吉,承天宠也”是说主帅身在军中指挥,吉利,因为得到上天的宠爱。此计运用此象理,是说将帅巧妙地运用此计,克敌制胜,就如同有上天护佑一样。
【按语】
庞统使曹操战舰勾连,而后纵火焚之,使不得脱。则连环计者,其结在使敌自累,而后图之。盖一计累敌,—计攻敌,两计扣用,以摧强势也。如宋毕再遇赏引敌与战,且前且却,至于数四。视日已晚,乃以香料煮黑,布地上。复前博战,佯败走。敌乘胜追逐。其马已饥,闻豆香,乃就食,鞭之不前。遇率师反攻,遂大胜。皆连环之计也。
【故事】
献貂蝉王允除董卓。
指战争中看到形势对自己极为不利时就逃走。现多用于做事时如果形势不利没有成功的希望时就选择退却、逃避的态度。
【原典】
全师避敌①。左次无咎,未失常也②
【注释】
①全师避敌:全军退却,避开强敌。
②左次无咎:未失常也:语出《易经.师》卦(卦名解释见前二十六计注)。本卦六四.《象》辞:“左次无咎,未失常也。”是说军队在左边扎营,没有危险,(因为扎营或左边或右边,要依时情而定)并没有违背行军常道。
【按语】
敌势全胜,我不能战。则:必降;必和;必走。降则全败,和则半败,走则未败。未败者,胜之转机也。如宋毕再遇与金人对垒,度金兵至者日众,难与争锋。—夕拔营去,留旗帜于营,豫缚生羊悬之,置其前二足于鼓上,羊不堪悬,则足击鼓有声。金人不觉为空营,相持数日,乃觉,欲追之,则已远矣。(《战略考.南宋》)可谓善走者矣。
上半年看了一些书,简单总结一下
古人云:“活到老,学到老。” IT技术发展太快,行业日新月异,作为最苦逼职业之一,软件工程师,只能不停的学习、深造、提升。总之,学不可以已,所以,保持良好的心态,持之以恒,这个很重要。
以下是今年上半年阅读的相关书籍,这里分享七本:
微服务到底意味着什么?它与以往的开发架构有何不同?
最近几年,越来越多的开发人员使用“微服务”一词来阐述他们的系统或应用架构,当然或许这只是他们在吹嘘自己在技术潮流中并未落伍。我认为,IT科技行业的人士至少要了解微服务的基础知识,因为它代表着未来的发展方向。即使对我的话半信半疑,还有行业内很多大神为我背书。只是,话说回来,到底什么是微服务呢?
近年来大数据BigData、人工智能AI、物联网Iot等行业发展迅猛,很多人都想要从事大数据技术开发工作,但是,请问要怎么做,路线是什么?从哪里开始学?学哪些?这是一个大问题。对于我自己来说,最近也在学一些大数据开发相关的技术,所以之前整理了一份《大数据技术学习路线》,希望对你有所帮助。
Java最早是由SUN公司(已被Oracle收购)的詹姆斯·高斯林(高司令,人称Java之父)在上个世纪90年代初开发的一种编程语言。
java的运行机制:Java是将代码编译成一种“字节码”,它类似于抽象的CPU指令,然后,针对不同平台编写虚拟机,不同平台的虚拟机负责加载字节码并执行,这样就实现了“一次编写,到处运行”的效果。
从互联网到企业平台,Java是应用最广泛的编程语言,原因在于:
Java语言常年霸占着三大市场:
这意味着Java拥有最广泛的就业市场。随着Java的发展,SUN给Java又分出了三个不同版本:
因此我们推荐的Java学习路线图如下:
无论怎么选择,Java SE的核心技术是基础,这个教程的目的就是让你完全精通Java SE!
java名词解释:
首先到官网下载jdk:https://www.oracle.com/java/technologies/javase-jdk14-downloads.html,然后安装;
安装完JDK后,需要设置一个JAVA_HOME的环境变量,它指向JDK的安装目录。在Windows下,它是安装目录,类似:1
C:\Program Files\Java\jdk-14
然后,把JAVA_HOME的bin目录附加到系统环境变量PATH上。在Windows下,它长这样:
1 | Path=%JAVA_HOME%\bin;<现有的其他路径> |
在Mac下,它在~/.bash_profile或~/.zprofile里,它是:
1 | export JAVA_HOME=`/usr/libexec/java_home -v 14` |
把JAVA_HOME的bin目录添加到PATH中是为了在任意文件夹下都可以运行java。打开命令提示符窗口,输入命令java -version,可以看到java的版本,则jdk安装正常。
细心的童鞋还可以在JAVA_HOME的bin目录下找到很多可执行文件:
java程序的运行:
一个Java源码只能定义一个public类型的class,并且class名称和文件名要完全一致;
使用javac可以将.java源码编译成.class字节码(使用命令:javac Hello.java);
使用java可以运行一个已编译的Java程序,参数是类名(使用命令:java Hello)。
javac是个java语言编译器,它的用法:
它的作用是把java程序编写的类和接口编译成字节代码的class文件
而java命令程序则是一个解释器,它的作用是把编译后生成的class文件解释成机器能够识别的机器码,并最终由运行环境中的Runtime对代码进行运行,真正实现我们想要机器完成的工作。从截图的帮助文档中我们看到它要执行的是类,是一个和class文件名字完全相同(大小写也要一样)的类
java 命令的作用就是Java虚拟机的作用,虚拟机的功能如下:
IDE是集成开发环境:Integrated Development Environment的缩写。
使用IDE的好处在于按,可以把编写代码、组织项目、编译、运行、调试等放到一个环境中运行,能极大地提高开发效率。IDE提升开发效率主要靠以下几点:
目前,流行的用于Java开发的IDE有:
Eclipse:Eclipse是由IBM开发并捐赠给开源社区的一个IDE,也是目前应用最广泛的IDE。Eclipse的特点是它本身是Java开发的,并且基于插件结构,即使是对Java开发的支持也是通过插件JDT实现的。
除了用于Java开发,Eclipse配合插件也可以作为C/C++开发环境、PHP开发环境、Rust开发环境等。
IntelliJ Idea:IntelliJ Idea是由JetBrains公司开发的一个功能强大的IDE,分为免费版和商用付费版。JetBrains公司的IDE平台也是基于IDE平台+语言插件的模式,支持Python开发环境、Ruby开发环境、PHP开发环境等,这些开发环境也分为免费版和付费版。
NetBeans:NetBeans是最早由SUN开发的开源IDE,由于使用人数较少,目前已不再流行。